<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ROS2节点通信实现零拷贝]]></title><description><![CDATA[<p dir="auto">下面的一个例子演示了两个节点之间如何实现零拷贝通讯。</p>
<p dir="auto">注意，下面测试例子的<code>ROS2</code>版本为<code>Galactic</code>。</p>
<pre><code class="language-c++">#include &lt;chrono&gt;
#include &lt;cinttypes&gt;
#include &lt;cstdio&gt;
#include &lt;memory&gt;
#include &lt;string&gt;
#include &lt;utility&gt;

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

using namespace std::chrono_literals;

// Node that produces messages.
struct Producer : public rclcpp::Node
{
  Producer(const std::string &amp; name, const std::string &amp; output)
  : Node(name, rclcpp::NodeOptions().use_intra_process_comms(true))
  {
    // Create a publisher on the output topic.
    pub_ = this-&gt;create_publisher&lt;std_msgs::msg::Int32&gt;(output, 10);
    std::weak_ptr&lt;std::remove_pointer&lt;decltype(pub_.get())&gt;::type&gt; captured_pub = pub_;
    // Create a timer which publishes on the output topic at ~1Hz.
    auto callback = [captured_pub]() -&gt; void {
        auto pub_ptr = captured_pub.lock();
        if (!pub_ptr) {
          return;
        }
        static int32_t count = 0;
        std_msgs::msg::Int32::UniquePtr msg(new std_msgs::msg::Int32());
        msg-&gt;data = count++;
        printf(
          "Published message with value: %d, and address: 0x%" PRIXPTR "\n", msg-&gt;data,
          reinterpret_cast&lt;std::uintptr_t&gt;(msg.get()));
        pub_ptr-&gt;publish(std::move(msg));
      };
    timer_ = this-&gt;create_wall_timer(1s, callback);
  }

  rclcpp::Publisher&lt;std_msgs::msg::Int32&gt;::SharedPtr pub_;
  rclcpp::TimerBase::SharedPtr timer_;
};

// Node that consumes messages.
struct Consumer : public rclcpp::Node
{
  Consumer(const std::string &amp; name, const std::string &amp; input)
  : Node(name, rclcpp::NodeOptions().use_intra_process_comms(true))
  {
    // Create a subscription on the input topic which prints on receipt of new messages.
    sub_ = this-&gt;create_subscription&lt;std_msgs::msg::Int32&gt;(
      input,
      10,
      [](std_msgs::msg::Int32::UniquePtr msg) {
        printf(
          " Received message with value: %d, and address: 0x%" PRIXPTR "\n", msg-&gt;data,
          reinterpret_cast&lt;std::uintptr_t&gt;(msg.get()));
      });
  }

  rclcpp::Subscription&lt;std_msgs::msg::Int32&gt;::SharedPtr sub_;
};

int main(int argc, char * argv[])
{
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  rclcpp::init(argc, argv);
  rclcpp::executors::SingleThreadedExecutor executor;

  auto producer = std::make_shared&lt;Producer&gt;("producer", "number");
  auto consumer = std::make_shared&lt;Consumer&gt;("consumer", "number");

  executor.add_node(producer);
  executor.add_node(consumer);
  executor.spin();

  rclcpp::shutdown();

  return 0;
}
</code></pre>
<p dir="auto">例子中节点的建立有几点需要注意：</p>
<ol>
<li>使能<code>intra_process</code></li>
</ol>
<pre><code class="language-c++">Node(name, rclcpp::NodeOptions().use_intra_process_comms(true))
</code></pre>
<p dir="auto">配置节点时要开启<code>intra_process</code>。</p>
<ol start="2">
<li>发布消息时使用<code>UniquePtr</code>和<code>std::move(msg)</code></li>
</ol>
<p dir="auto">除了上面例子中的写法，还可以采用下面的写法：</p>
<pre><code class="language-c++">auto dis = std::make_unique&lt;std_msgs::msg::Float32&gt;();
dis-&gt;data = 10.0;
pub_-&gt;publish(std::move(dis));
</code></pre>
<ol start="3">
<li>将需通信的节点加入到同一个进程中</li>
</ol>
<pre><code class="language-c++">  rclcpp::executors::SingleThreadedExecutor executor;

  auto producer = std::make_shared&lt;Producer&gt;("producer", "number");
  auto consumer = std::make_shared&lt;Consumer&gt;("consumer", "number");

  executor.add_node(producer);
  executor.add_node(consumer);
</code></pre>
<p dir="auto">完整的功能代码可通过下面的链接获取：</p>
<p dir="auto"><a href="https://github.com/shoufei403/ros2_galactic_tutorials" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/shoufei403/ros2_galactic_tutorials</a></p>
<p dir="auto">相应的代码在<code>demos/intra_process_demo</code>目录。</p>
<p dir="auto">编译好代码后使用下面的命令启动示例程序</p>
<pre><code class="language-bash">source install/setup.bash
ros2 run intra_process_demo two_node_pipeline
</code></pre>
<p dir="auto">输出结果：</p>
<pre><code class="language-bash">Published message with value: 0, and address: 0x5625E3159130
 Received message with value: 0, and address: 0x5625E3159130
Published message with value: 1, and address: 0x5625E3159130
 Received message with value: 1, and address: 0x5625E3159130
Published message with value: 2, and address: 0x5625E3159130
 Received message with value: 2, and address: 0x5625E3159130
Published message with value: 3, and address: 0x5625E3159130
 Received message with value: 3, and address: 0x5625E3159130
Published message with value: 4, and address: 0x5625E3159130
 Received message with value: 4, and address: 0x5625E3159130
Published message with value: 5, and address: 0x5625E3159130
 Received message with value: 5, and address: 0x5625E3159130
Published message with value: 6, and address: 0x5625E3159130
 Received message with value: 6, and address: 0x5625E3159130
Published message with value: 7, and address: 0x5625E3159130
 Received message with value: 7, and address: 0x5625E3159130
Published message with value: 8, and address: 0x5625E3159130
 Received message with value: 8, and address: 0x5625E3159130
Published message with value: 9, and address: 0x5625E3159130
 Received message with value: 9, and address: 0x5625E3159130
</code></pre>
<p dir="auto"><strong>可以发现</strong>，发送端数据的地址和接收端数据地址是一致的。所以发送端只是把数据存放的地址发送给了接收端并没有发生数据拷贝。</p>
<p dir="auto">零拷贝的特性对于传输图像数据尤为有用。关于图像传输的例子请参看<code>demos/intra_process_demo</code>目录中的其他例子。</p>
<p dir="auto">参考：</p>
<p dir="auto"><a href="https://docs.ros.org/en/galactic/Tutorials/Demos/Intra-Process-Communication.html" target="_blank" rel="noopener noreferrer nofollow ugc">https://docs.ros.org/en/galactic/Tutorials/Demos/Intra-Process-Communication.html</a></p>
]]></description><link>https://fishros.org.cn/forum/topic/494/ros2节点通信实现零拷贝</link><generator>RSS for Node</generator><lastBuildDate>Sun, 10 May 2026 05:00:12 GMT</lastBuildDate><atom:link href="https://fishros.org.cn/forum/topic/494.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 24 Jul 2022 00:51:17 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Wed, 30 Oct 2024 12:58:57 GMT]]></title><description><![CDATA[<p dir="auto">你好，use_intra_process_comms没有Python版本的吗？</p>
]]></description><link>https://fishros.org.cn/forum/post/13717</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/13717</guid><dc:creator><![CDATA[wanglehui8357]]></dc:creator><pubDate>Wed, 30 Oct 2024 12:58:57 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Fri, 31 Mar 2023 04:12:34 GMT]]></title><description><![CDATA[<p dir="auto">所以他没有走中间层，对吗？这个性能 怎么测试呢？</p>
]]></description><link>https://fishros.org.cn/forum/post/5438</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/5438</guid><dc:creator><![CDATA[alexleel]]></dc:creator><pubDate>Fri, 31 Mar 2023 04:12:34 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Sat, 30 Jul 2022 22:25:15 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/399">@首飞Kevin</a> 是的</p>
]]></description><link>https://fishros.org.cn/forum/post/2161</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2161</guid><dc:creator><![CDATA[李东武]]></dc:creator><pubDate>Sat, 30 Jul 2022 22:25:15 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Sat, 30 Jul 2022 14:46:29 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/680">@李东武</a> cyberrt是Apollo的那套通讯框架吗？</p>
]]></description><link>https://fishros.org.cn/forum/post/2160</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2160</guid><dc:creator><![CDATA[首飞Kevin]]></dc:creator><pubDate>Sat, 30 Jul 2022 14:46:29 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Sat, 30 Jul 2022 14:37:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/399">@首飞Kevin</a> 我现在用国产芯片 他们移植的cyberrt</p>
<p dir="auto">也加入了零拷贝 不过是进程间的  cyberrt本身进程内就是共享内存的</p>
]]></description><link>https://fishros.org.cn/forum/post/2158</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2158</guid><dc:creator><![CDATA[李东武]]></dc:creator><pubDate>Sat, 30 Jul 2022 14:37:01 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 03:40:12 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/399">@首飞Kevin</a> 我也这么认为，互相共享对象地址，某种意义上说也是共享内存了哈哈</p>
]]></description><link>https://fishros.org.cn/forum/post/2065</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2065</guid><dc:creator><![CDATA[小鱼]]></dc:creator><pubDate>Mon, 25 Jul 2022 03:40:12 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 03:37:11 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/344">@young</a> 感觉不是共享内存。因为没有涉及到不同进程。</p>
]]></description><link>https://fishros.org.cn/forum/post/2063</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2063</guid><dc:creator><![CDATA[首飞Kevin]]></dc:creator><pubDate>Mon, 25 Jul 2022 03:37:11 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 02:37:19 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/399">@首飞Kevin</a> 这是共享内存吗？</p>
]]></description><link>https://fishros.org.cn/forum/post/2055</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2055</guid><dc:creator><![CDATA[young]]></dc:creator><pubDate>Mon, 25 Jul 2022 02:37:19 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 02:25:42 GMT]]></title><description><![CDATA[<p dir="auto"><a class="mention plugin-mentions-user plugin-mentions-a" href="https://fishros.org.cn/forum/uid/399">@首飞Kevin</a> ROS2官方确实没有提这个，这部分工作其实在dds中有做，比如你用fastdds,需要修改dds配置文件可以实共享内存通信。</p>
<p dir="auto">若要在进程间启用数据共享，需要在 XML 和设置上具有以下各项RMW_FASTRTPS_USE_QOS_FROM_XML=1</p>
<p dir="auto">&lt;data_writer profile_name="topic_name"&gt;<br />
&lt;qos&gt;<br />
&lt;data_sharing&gt;<br />
&lt;kind&gt;AUTOMATIC&lt;/kind&gt;<br />
&lt;/data_sharing&gt;<br />
&lt;/qos&gt;<br />
&lt;/data_writer&gt;</p>
<p dir="auto">&lt;data_reader profile_name="topic_name"&gt;<br />
&lt;qos&gt;<br />
&lt;data_sharing&gt;<br />
&lt;kind&gt;AUTOMATIC&lt;/kind&gt;<br />
&lt;/data_sharing&gt;<br />
&lt;/qos&gt;<br />
&lt;/data_reader&gt;</p>
<p dir="auto">关于XML配置的具体使用：<a href="https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/xml_configuration.html" target="_blank" rel="noopener noreferrer nofollow ugc">https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/xml_configuration.html</a></p>
]]></description><link>https://fishros.org.cn/forum/post/2052</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2052</guid><dc:creator><![CDATA[小鱼]]></dc:creator><pubDate>Mon, 25 Jul 2022 02:25:42 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 01:00:19 GMT]]></title><description><![CDATA[<p dir="auto">@dongwu_li ROS2官方的这个示例是在一个进程中跑两个节点。然后节点间通讯实现零拷贝。这个效果和ROS1中的nodelet是一样的。官方没有不同进程间零拷贝通讯的例子。估计是没有这个功能的。但TogetherROS（地平线基于foxy优化的ROS2版本）中的rclcpp实现了进程间的零拷贝通讯。</p>
]]></description><link>https://fishros.org.cn/forum/post/2049</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2049</guid><dc:creator><![CDATA[首飞Kevin]]></dc:creator><pubDate>Mon, 25 Jul 2022 01:00:19 GMT</pubDate></item><item><title><![CDATA[Reply to ROS2节点通信实现零拷贝 on Mon, 25 Jul 2022 00:43:26 GMT]]></title><description><![CDATA[<p dir="auto">请教一个问题  ros2中零拷贝只能在同一进程中的不同线程之间吗？不同进程间可以吗？</p>
]]></description><link>https://fishros.org.cn/forum/post/2047</link><guid isPermaLink="true">https://fishros.org.cn/forum/post/2047</guid><dc:creator><![CDATA[李东武]]></dc:creator><pubDate>Mon, 25 Jul 2022 00:43:26 GMT</pubDate></item></channel></rss>