【同一进程组织多个节点】

【同一进程组织多个节点】

注:战队现使用可组合节点组织多节点

使用执行器组织节点

示例

int main(int argc,char** argv){
	rclcpp::init();
	rclcpp::executors::SingThreadedExecutor executor;
	auto node1=std::make_shared<Node>("node1");
	auto node2=std::make_shared<Node>("node2");
	executor.add_node(producer);
	executor.add_node(consumer);
	executor.spin();
	rclcpp::shutdown();
	return 0;
}

零复制传输:直接传递数据地址,不进行数据复制

订阅者接收到数据的内存地址和发布者相同
※适用条件:在同一主机进行数据传输

工程示例

src/include/learn_compose内编写hpp
src/src内编写cpp

发送端

talker.hpp

#ifndef LEARN_COMPOSE__TALKER_COMPONENT_HPP_
#define LEARN_COMPOSE__TALKER_COMPONENT_HPP_

#include"rclcpp/rclcpp.hpp"
#include"std_msgs/msg/int32.hpp"

//命名空间:防止外面的Talker和learn_compose里的Talker发生冲突
namespace learn_compose{
    class Talker : public rclcpp::Node{
        public:
            explicit Talker(const rclcpp::NodeOptions &options);

        private:
            int32_t count_;
            rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr pub_;
            rclcpp::TimerBase::SharedPtr timer_;
    };
}//namespace learn_compose

#endif //LEARN_COMPOSE__TALKER_COMPONENT_HPP_

talker.cpp

#include <chrono>
#include "learn_compose/talker.hpp"

namespace learn_compose{
    using namespace std::chrono_literals;
    Talker::Talker(const rclcpp::NodeOptions &options) : Node("talker",options){
        pub_=this->create_publisher<std_msgs::msg::Int32>("count",10);
        auto callback=[&]()->void{
            //独占式智能指针
            std_msgs::msg::Int32::UniquePtr msg(new std_msgs::msg::Int32());
            msg->data=count_++;
            RCLCPP_INFO(this->get_logger(),"发布数据:%d(0x%1X),msg->data",
                        reinterpret_cast<std::uintptr_t>(msg.get()));
                        //reinterpret_cast强制类型转换(偏底层)
            pub_->publish(std::move(msg));
        };
        timer_=this->create_wall_timer(1s,callback);
    }
}//namespace learn_compose

接收端

listener.hpp

#ifndef LEARN_COMPOSE__LISTENER_COMPONENT_HPP_
#define LEARN_COMPOSE__LISTENER_COMPONENT_HPP_

#include"rclcpp/rclcpp.hpp"
#include"std_msgs/msg/int32.hpp"

namespace learn_compose{
    class Listener : public rclcpp::Node{
        public:
            explicit Listener(const rclcpp::NodeOptions &options);

        private:
            rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr sub_;
    };
}//namespace learn_compose

#endif //LEARN_COMPOSE__LISTENER_COMPONENT_HPP_

listener.cpp

#include"learn_compose/listener.hpp"
#include<chrono>
namespace learn_compose{
    using namespace std::chrono_literals;
    Listener::Listener(const rclcpp::NodeOptions &options) : Node("listener",options){
        sub_=this->create_subscription<std_msgs::msg::Int32>(
            "count",10,[&](const std_msgs::msg::Int32::UniquePtr msg){
                RCLCPP_INFO(this->get_logger(),"收到数据:%d(0x%1X)",msg->data,
                            reinterpret_cast<std::uintptr_t>(msg.get()));
            }
        );
    }
}//namespace learn_compose

主进程 intra_process_pubsub.cpp

#include"learn_compose/listener.hpp"
#include"learn_compose/talker.hpp"
#include"rclcpp/rclcpp.hpp"

int main(int argc,char** argv){
    rclcpp::init(argc,argv);
    rclcpp::executors::SingleThreadedExecutor executor;

    rclcpp::NodeOptions options;//创建节点选项
    options.use_intra_process_comms(true);//使用进程内通信
    auto talker=std::make_shared<learn_compose::Talker>(options);
    auto listener=std::make_shared<learn_compose::Listener>(options);

    executor.add_node(talker);
    executor.add_node(listener);
    executor.spin();

    rclcpp::shutdown();
    return 0;
}

CMakeList.txt

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp_components REQUIRED)

//包含库(include文件)
include_directories(include)

//一个exe要由三份代码构建
add_executable(intra_process_pubsub
          src/intra_process_pubsub.cpp
          src/talker.cpp
          src/listener.cpp
) 

ament_target_dependencies(intra_process_pubsub std_msgs rclcpp rclcpp_components)

install(TARGETS intra_process_pubsub
        DESTINATION lib/${PROJECT_NAME})

运行结果
image

使用组件组合节点

功能
可动态的将不同节点加载到一个进程,也可动态卸载

命令行(利用示例程序)

//查看已经注册的可用组件
$ ros2 component types
composition
  composition::Talker
  composition::Listener
  composition::NodeLikeListener
  composition::Server
  composition::Client
//启动节点容器(组件管理器)
$ ros2 run rclcpp_components component_container --ros-args -r __node:=component_test
//查看组件列表
$ ros2 component list
/component_test
//将节点加载到组件容器内
$ ros2 component load /component_test composition composition::Talker
Loaded component 1 into '/component_test' container node as '/talker'
$ ros2 component load /component_test composition composition::Listener
Loaded component 2 into '/component_test' container node as '/listener'
/*
修改节点名字 --node-name talker3
修改节点命名空间 --node-namespace /ns
传递参数值 -p name:=value
*/
//卸载节点
$ ros2 component list
/component_test
  1  /talker
  2  /listener
$ ros2 component unload /component_test 1 2
Unloaded component 1 from '/component_test' container node
Unloaded component 2 from '/component_test' container node

image

在启动文件动态加载/卸载

# 示例:启动component_test并加载Talker和Listener节点
import launch
from launch_ros.actions import ComposableNodeContainer
from launch_ros.discriptions import ComposableNode

def generate_launch_description():
	continer=ComposableNodeContainer(
		name='component_test'
		namespace=''
		package='rclcpp_components'
		executable='component_container',
		composable_node_description=[
			ComposableNode(
				package='composition',
				plugin='composition::Talker',
				name='talker'
			),
			ComposableNode(
				package='composition',
				plugin='composition::Listener',
				name='listener'
			),
		],
		output='screen',
	)
return launch.LaunchDescription([continer])

编写自己的节点

(1)提供const rclcpp::NodeOptions &作为参数的构造函数
(2)对节点类进行注册

注册节点为组件

cpp文件内

#include"rclcpp_components/register_node_macro.hpp"
RCLCPP_COMPONENTS_REGISTER_NODE(learn_compose::Talker/Listener)

CMakeLists.txt

# 生成动态库
add_library(talker_component SHARED src/talker.cpp)
ament_target_dependencies(talker_component "std_msgs" "rclcpp" "rclcpp_components")
rclcpp_components_register_nodes(talker_component "learn_compose::Talker")

add_library(listener_component SHARED src/listener.cpp)
ament_target_dependencies(listener_component "std_msgs" "rclcpp" "rclcpp_components")
rclcpp_components_register_nodes(listener_component "learn_compose::Listener")

install(TARGETS talker_component listener_component
      ARCHIVE DESTINATION lib
      LIBRARY DESTINATION lib
      RUNTIME DESTINATION bin
)

image
image
image
image

posted @ 2025-01-09 15:34  White_ink  阅读(135)  评论(0)    收藏  举报