国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

易企秀微網(wǎng)站如何做文字鏈接seo怎么去優(yōu)化

易企秀微網(wǎng)站如何做文字鏈接,seo怎么去優(yōu)化,太原醫(yī)療網(wǎng)站建設(shè),怎樣查看網(wǎng)站備案號目標(biāo):本教程將展示如何在 ROS 2 中使用 Fast DDS 的擴(kuò)展配置功能。 教程級別:高級 時間:20 分鐘 目錄 背景 先決條件在同一個節(jié)點(diǎn)中混合同步和異步發(fā)布 創(chuàng)建具有發(fā)布者的節(jié)點(diǎn)創(chuàng)建包含配置文件的 XML 文件執(zhí)行發(fā)布者節(jié)點(diǎn)創(chuàng)建一個包含訂閱者的節(jié)…

目標(biāo):本教程將展示如何在 ROS 2 中使用 Fast DDS 的擴(kuò)展配置功能

?教程級別:高級

?時間:20 分鐘

?目錄

  • ?背景

  • ?先決條件

  • 在同一個節(jié)點(diǎn)中混合同步和異步發(fā)布

    • 創(chuàng)建具有發(fā)布者的節(jié)點(diǎn)

    • 創(chuàng)建包含配置文件的 XML 文件

    • 執(zhí)行發(fā)布者節(jié)點(diǎn)

    • 創(chuàng)建一個包含訂閱者的節(jié)點(diǎn)

    • 執(zhí)行訂閱者節(jié)點(diǎn)

    • 示例分析

  • 使用其他 FastDDS 功能與 XML

    • 限制匹配訂閱者的數(shù)量

    • 在主題內(nèi)使用分區(qū)

  • 配置服務(wù)和客戶端

    • 使用服務(wù)和客戶端創(chuàng)建節(jié)點(diǎn)

    • 為服務(wù)和客戶端創(chuàng)建 XML 配置文件

    • 執(zhí)行節(jié)點(diǎn)

?背景

ROS 2 堆棧和 Fast DDS 之間的接口由 ROS 2 中間件實(shí)現(xiàn) rmw_fastrtps 提供。此實(shí)現(xiàn)可在所有 ROS 2 發(fā)行版中使用,無論是從二進(jìn)制文件還是從源代碼。

ROS 2 RMW 僅允許配置某些中間件 QoS(參見 ROS 2 QoS 策略 https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html )。然而,?rmw_fastrtps?提供了擴(kuò)展的配置功能,以充分利用 Fast DDS 中的功能。本教程將通過一系列示例指導(dǎo)您如何使用 XML 文件解鎖此擴(kuò)展配置。

為了獲得有關(guān)在 ROS 2 上使用 Fast DDS 的更多信息,請查看以下文檔。https://fast-dds.docs.eprosima.com/en/latest/fastdds/ros2/ros2.html

5b7a953ff3efb2f4844d24ef9b3eea1f.png

sudo?apt?install?ros-jazzy-rmw-fastrtps-cpp
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export RMW_IMPLEMENTATION=rmw_fastrtps_dynamic_cpp
RMW_IMPLEMENTATION=rmw_fastrtps_cpp ros2 run <package> <application>
RMW_IMPLEMENTATION=rmw_fastrtps_dynamic_cpp ros2 run <package> <application>

先決條件

本教程假設(shè)您知道如何創(chuàng)建一個包。它還假設(shè)您知道如何編寫一個簡單的發(fā)布者和訂閱者以及一個簡單的服務(wù)和客戶端。盡管示例是用 C++實(shí)現(xiàn)的,但相同的概念也適用于 Python 包。

在同一個節(jié)點(diǎn)中混合同步和異步發(fā)布

在這個第一個例子中,將創(chuàng)建一個具有兩個發(fā)布者的節(jié)點(diǎn),其中一個是同步發(fā)布模式,另一個是異步發(fā)布模式。

rmw_fastrtps?默認(rèn)使用同步發(fā)布模式。

在同步發(fā)布模式下,數(shù)據(jù)直接在用戶線程的上下文中發(fā)送。這意味著在寫操作期間發(fā)生的任何阻塞調(diào)用都會阻塞用戶線程,從而阻止應(yīng)用程序繼續(xù)運(yùn)行。然而,由于線程之間沒有通知或上下文切換,這種模式通常在較低的延遲下產(chǎn)生更高的吞吐量。

另一方面,在異步發(fā)布模式下,每次發(fā)布者調(diào)用寫操作時,數(shù)據(jù)會被復(fù)制到隊列中,后臺線程(異步線程)會收到有關(guān)隊列中新增數(shù)據(jù)的通知,并在數(shù)據(jù)實(shí)際發(fā)送之前將線程的控制權(quán)返回給user。后臺線程負(fù)責(zé)消費(fèi)隊列并將數(shù)據(jù)發(fā)送給每個匹配的reader。

創(chuàng)建帶有發(fā)布者的節(jié)點(diǎn)

首先,在新的工作區(qū)上創(chuàng)建一個名為?sync_async_node_example_cpp?的新包:

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cpp

4332bab791460afb18fd668dfa2ae421.png

然后,向包中添加一個名為?src/sync_async_writer.cpp?的文件,內(nèi)容如下。請注意,同步發(fā)布者將發(fā)布在主題?sync_topic?上,而異步發(fā)布者將發(fā)布在主題?async_topic?上。

#include <chrono> // 包含用于時間操作的頭文件
#include <functional> // 包含用于函數(shù)對象和綁定的頭文件
#include <memory> // 包含用于智能指針的頭文件
#include <string> // 包含用于字符串操作的頭文件#include "rclcpp/rclcpp.hpp" // 包含ROS 2的C++客戶端庫
#include "std_msgs/msg/string.hpp" // 包含標(biāo)準(zhǔn)消息類型Stringusing namespace std::chrono_literals; // 使用chrono命名空間中的字面量class SyncAsyncPublisher : public rclcpp::Node // 定義一個名為SyncAsyncPublisher的類,繼承自rclcpp::Node
{
public:SyncAsyncPublisher() // 構(gòu)造函數(shù): Node("sync_async_publisher"), count_(0) // 初始化節(jié)點(diǎn)名稱為sync_async_publisher,計數(shù)器count_初始化為0{// 創(chuàng)建一個同步發(fā)布者,發(fā)布到主題'sync_topic'sync_publisher_ = this->create_publisher<std_msgs::msg::String>("sync_topic", 10);// 創(chuàng)建一個異步發(fā)布者,發(fā)布到主題'async_topic'async_publisher_ = this->create_publisher<std_msgs::msg::String>("async_topic", 10);// 定義一個定時器回調(diào)函數(shù),每次定時器觸發(fā)時執(zhí)行的操作auto timer_callback = this{// 創(chuàng)建一個新的消息auto sync_message = std_msgs::msg::String();sync_message.data = "SYNC: Hello, world! " + std::to_string(count_);// 將消息記錄到控制臺以顯示進(jìn)度RCLCPP_INFO(this->get_logger(), "Synchronously publishing: '%s'", sync_message.data.c_str());// 使用同步發(fā)布者發(fā)布消息sync_publisher_->publish(sync_message);// 創(chuàng)建一個新的消息auto async_message = std_msgs::msg::String();async_message.data = "ASYNC: Hello, world! " + std::to_string(count_);// 將消息記錄到控制臺以顯示進(jìn)度RCLCPP_INFO(this->get_logger(), "Asynchronously publishing: '%s'", async_message.data.c_str());// 使用異步發(fā)布者發(fā)布消息async_publisher_->publish(async_message);// 準(zhǔn)備下一條消息的計數(shù)count_++;};// 創(chuàng)建一個定時器,每隔半秒觸發(fā)一次,執(zhí)行定時器回調(diào)函數(shù)timer_ = this->create_wall_timer(500ms, timer_callback);}private:// 定時器,每隔半秒觸發(fā)一次,發(fā)布新的數(shù)據(jù)rclcpp::TimerBase::SharedPtr timer_;// 異步發(fā)布者rclcpp::Publisher<std_msgs::msg::String>::SharedPtr async_publisher_;// 同步發(fā)布者rclcpp::Publisher<std_msgs::msg::String>::SharedPtr sync_publisher_;// 已發(fā)送的消息數(shù)量size_t count_;
};int main(int argc, char * argv[]) // 主函數(shù)
{rclcpp::init(argc, argv); // 初始化ROS 2rclcpp::spin(std::make_shared<SyncAsyncPublisher>()); // 創(chuàng)建SyncAsyncPublisher節(jié)點(diǎn)并運(yùn)行rclcpp::shutdown(); // 關(guān)閉ROS 2return 0; // 返回0表示程序正常結(jié)束
}

現(xiàn)在打開?CMakeLists.txt?文件,添加一個新的可執(zhí)行文件并將其命名為?SyncAsyncWriter?,以便您可以使用?ros2?run?運(yùn)行您的節(jié)點(diǎn):

add_executable(SyncAsyncWriter src/sync_async_writer.cpp)
ament_target_dependencies(SyncAsyncWriter rclcpp std_msgs)

最后,添加?install(TARGETS…)?部分,以便?ros2?run?可以找到你的可執(zhí)行文件:

install(TARGETSSyncAsyncWriterDESTINATION lib/${PROJECT_NAME})

您可以通過刪除一些不必要的部分和注釋來清理您的?CMakeLists.txt?,使其看起來像這樣:

cmake_minimum_required(VERSION 3.8) # 設(shè)置CMake的最低版本要求為3.8
project(sync_async_node_example_cpp) # 定義項(xiàng)目名稱為sync_async_node_example_cpp# 默認(rèn)使用C++14標(biāo)準(zhǔn)
if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14) # 如果沒有設(shè)置C++標(biāo)準(zhǔn),則設(shè)置為C++14
endif()# 如果使用GNU編譯器或Clang編譯器,添加編譯選項(xiàng)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) # 添加編譯選項(xiàng):顯示所有警告、額外警告和嚴(yán)格警告
endif()find_package(ament_cmake REQUIRED) # 查找ament_cmake包,標(biāo)記為必需
find_package(rclcpp REQUIRED) # 查找rclcpp包,標(biāo)記為必需
find_package(std_msgs REQUIRED) # 查找std_msgs包,標(biāo)記為必需add_executable(SyncAsyncWriter src/sync_async_writer.cpp) # 添加可執(zhí)行文件SyncAsyncWriter,源文件為src/sync_async_writer.cpp
ament_target_dependencies(SyncAsyncWriter rclcpp std_msgs) # 設(shè)置SyncAsyncWriter的依賴項(xiàng)為rclcpp和std_msgsinstall(TARGETS # 安裝目標(biāo)SyncAsyncWriter # 安裝SyncAsyncWriterDESTINATION lib/${PROJECT_NAME}) # 安裝路徑為lib/${PROJECT_NAME}ament_package() # 聲明ament包

如果現(xiàn)在構(gòu)建并運(yùn)行此節(jié)點(diǎn),兩個發(fā)布者將表現(xiàn)相同,兩個發(fā)布者在主題中都異步發(fā)布,因?yàn)檫@是默認(rèn)的發(fā)布模式。默認(rèn)的發(fā)布模式配置可以在節(jié)點(diǎn)啟動期間使用 XML 文件在運(yùn)行時更改。

創(chuàng)建包含配置文件的 XML 文件

創(chuàng)建一個名為?SyncAsync.xml?的文件,并包含以下內(nèi)容:

cxy@ubuntu2404-cxy:~/ros2_ws/src/sync_async_node_example_cpp$?gedit?SyncAsync.xml
<?xml version="1.0" encoding="UTF-8" ?> <!-- XML聲明,定義版本和編碼 -->
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"> <!-- 定義profiles根元素,并指定其命名空間 --><!-- 默認(rèn)發(fā)布者配置文件 --><publisher profile_name="default_publisher" is_default_profile="true"> <!-- 定義一個發(fā)布者配置文件,名稱為default_publisher,設(shè)置為默認(rèn)配置文件 --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --></publisher><!-- 默認(rèn)訂閱者配置文件 --><subscriber profile_name="default_subscriber" is_default_profile="true"> <!-- 定義一個訂閱者配置文件,名稱為default_subscriber,設(shè)置為默認(rèn)配置文件 --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --></subscriber><!-- sync_topic主題的發(fā)布者配置文件 --><publisher profile_name="/sync_topic"> <!-- 定義一個發(fā)布者配置文件,名稱為/sync_topic --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --><qos> <!-- 定義QoS(服務(wù)質(zhì)量)設(shè)置 --><publishMode> <!-- 定義發(fā)布模式 --><kind>SYNCHRONOUS</kind> <!-- 設(shè)置發(fā)布模式為同步 --></publishMode></qos></publisher><!-- async_topic主題的發(fā)布者配置文件 --><publisher profile_name="/async_topic"> <!-- 定義一個發(fā)布者配置文件,名稱為/async_topic --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --><qos> <!-- 定義QoS(服務(wù)質(zhì)量)設(shè)置 --><publishMode> <!-- 定義發(fā)布模式 --><kind>ASYNCHRONOUS</kind> <!-- 設(shè)置發(fā)布模式為異步 --></publishMode></qos></publisher></profiles>

請注意,定義了多個發(fā)布者和訂閱者的配置文件。定義了兩個默認(rèn)配置文件,將?is_default_profile?設(shè)置為?true?,以及兩個名稱與先前定義的主題相符的配置文件:?sync_topic?和另一個?async_topic?。這兩個配置文件將發(fā)布模式分別設(shè)置為?SYNCHRONOUS?或?ASYNCHRONOUS?。還請注意,所有配置文件都指定了一個?historyMemoryPolicy?值,這是示例正常運(yùn)行所需的值,原因?qū)⒃诒窘坛毯竺娼忉尅?/p>

執(zhí)行發(fā)布者節(jié)點(diǎn)

您需要導(dǎo)出以下環(huán)境變量以加載 XML:

export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export RMW_FASTRTPS_USE_QOS_FROM_XML=1
export FASTRTPS_DEFAULT_PROFILES_FILE=~/ros2_ws/src/sync_async_node_example_cpp/SyncAsync.xml

最后,確保您已獲取設(shè)置文件并運(yùn)行節(jié)點(diǎn):

source install/setup.bash
ros2 run sync_async_node_example_cpp SyncAsyncWriter

您應(yīng)該看到發(fā)布者從發(fā)布節(jié)點(diǎn)發(fā)送數(shù)據(jù),如下所示:

[INFO] [1612972049.994630332] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 0'
[INFO] [1612972049.995097767] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 0'
[INFO] [1612972050.494478706] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 1'
[INFO] [1612972050.494664334] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 1'
[INFO] [1612972050.994368474] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 2'
[INFO] [1612972050.994549851] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 2'

現(xiàn)在你有一個同步發(fā)布者和一個異步發(fā)布者在同一個節(jié)點(diǎn)內(nèi)運(yùn)行。

779d7078955599ce9bb7995710049494.png

創(chuàng)建一個帶有訂閱者的節(jié)點(diǎn)

接下來,將創(chuàng)建一個包含訂閱者的新節(jié)點(diǎn),這些訂閱者將監(jiān)聽?sync_topic?和?async_topic?發(fā)布。在名為?src/sync_async_reader.cpp?的新源文件中寫入以下內(nèi)容:

#include <memory> // 包含用于智能指針的頭文件#include "rclcpp/rclcpp.hpp" // 包含ROS 2的C++客戶端庫
#include "std_msgs/msg/string.hpp" // 包含標(biāo)準(zhǔn)消息類型Stringclass SyncAsyncSubscriber : public rclcpp::Node // 定義一個名為SyncAsyncSubscriber的類,繼承自rclcpp::Node
{
public:SyncAsyncSubscriber() // 構(gòu)造函數(shù): Node("sync_async_subscriber") // 初始化節(jié)點(diǎn)名稱為sync_async_subscriber{// Lambda函數(shù),每次接收到新消息時運(yùn)行auto topic_callback = this{RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str()); // 將接收到的消息記錄到控制臺};// 創(chuàng)建一個同步訂閱者,訂閱主題'sync_topic'// 并將其綁定到topic_callbacksync_subscription_ = this->create_subscription<std_msgs::msg::String>("sync_topic", 10, topic_callback);// 創(chuàng)建一個異步訂閱者,訂閱主題'async_topic'// 并將其綁定到topic_callbackasync_subscription_ = this->create_subscription<std_msgs::msg::String>("async_topic", 10, topic_callback);}private:// 一個訂閱'sync_topic'主題的訂閱者rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sync_subscription_;// 一個訂閱'async_topic'主題的訂閱者rclcpp::Subscription<std_msgs::msg::String>::SharedPtr async_subscription_;
};int main(int argc, char * argv[]) // 主函數(shù)
{rclcpp::init(argc, argv); // 初始化ROS 2rclcpp::spin(std::make_shared<SyncAsyncSubscriber>()); // 創(chuàng)建SyncAsyncSubscriber節(jié)點(diǎn)并運(yùn)行rclcpp::shutdown(); // 關(guān)閉ROS 2return 0; // 返回0表示程序正常結(jié)束
}

打開?CMakeLists.txt?文件,在前一個?SyncAsyncWriter?下添加一個新的可執(zhí)行文件,并將其命名為?SyncAsyncReader

add_executable(SyncAsyncReader src/sync_async_reader.cpp)
ament_target_dependencies(SyncAsyncReader rclcpp std_msgs)install(TARGETSSyncAsyncReaderDESTINATION lib/${PROJECT_NAME})

執(zhí)行訂閱者節(jié)點(diǎn)

在一個終端中運(yùn)行發(fā)布者節(jié)點(diǎn)后,打開另一個終端并導(dǎo)出加載 XML 所需的環(huán)境變量:

export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export RMW_FASTRTPS_USE_QOS_FROM_XML=1
export FASTRTPS_DEFAULT_PROFILES_FILE=~/ros2_ws/src/sync_async_node_example_cpp/SyncAsync.xml

最后,確保您已獲取設(shè)置文件并運(yùn)行節(jié)點(diǎn):

source install/setup.bash
ros2 run sync_async_node_example_cpp SyncAsyncReader

您應(yīng)該看到訂閱者從發(fā)布節(jié)點(diǎn)接收數(shù)據(jù),如下所示:

[INFO] [1612972054.495429090] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 10'
[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'
[INFO] [1612972055.495453494] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 11'
[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'
[INFO] [1612972056.495534818] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 12'
[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12'

360ce14b2d48f0ad53fef08614cbfae6.png

示例分析

配置文件 XML

XML 文件定義了發(fā)布者和訂閱者的幾種配置。您可以擁有一個默認(rèn)的發(fā)布者配置文件和幾個特定主題的發(fā)布者配置文件。唯一的要求是所有發(fā)布者配置文件必須有不同的名稱,并且只能有一個默認(rèn)配置文件。訂閱者也是如此。

為了定義特定主題的配置,只需將配置文件命名為 ROS 2 主題名稱(如示例中的?/sync_topic?和?/async_topic?),?rmw_fastrtps?將此配置文件應(yīng)用于該主題的所有發(fā)布者和訂閱者。默認(rèn)配置文件由屬性?is_default_profile?設(shè)置為?true?標(biāo)識,并在沒有其他名稱與主題名稱匹配的配置文件時充當(dāng)回退配置文件。

環(huán)境變量?FASTRTPS_DEFAULT_PROFILES_FILE?用于通知 Fast DDS 配置文件的 XML 文件路徑。

RMW_FASTRTPS_USE_QOS_FROM_XML

在所有可配置屬性中,?rmw_fastrtps?對?publishMode?和?historyMemoryPolicy?的處理方式不同。默認(rèn)情況下,這些值在?rmw_fastrtps?實(shí)現(xiàn)中設(shè)置為?ASYNCHRONOUS?和?PREALLOCATED_WITH_REALLOC?,并且 XML 文件中設(shè)置的值將被忽略。為了使用 XML 文件中的值,必須將環(huán)境變量?RMW_FASTRTPS_USE_QOS_FROM_XML?設(shè)置為?1?。

然而,這還涉及另一個警告:如果設(shè)置了?RMW_FASTRTPS_USE_QOS_FROM_XML?,但 XML 文件沒有定義?publishMode?或?historyMemoryPolicy?,這些屬性將采用 Fast DDS 默認(rèn)值而不是?rmw_fastrtps?默認(rèn)值。這一點(diǎn)很重要,尤其是對于?historyMemoryPolicy?,因?yàn)?Fast DDS 默認(rèn)值是?PREALLOCATED?,它不適用于 ROS2 主題數(shù)據(jù)類型。因此,在示例中,已明確設(shè)置了該策略的有效值(?DYNAMIC?)。

rmw_qos_profile_t 的優(yōu)先級?

ROS 2 QoS 包含在 rmw_qos_profile_t https://docs.ros.org/en/jazzy/p/rmw/generated/structrmw__qos__profile__s.html中的 QoS 始終被遵守,除非設(shè)置為?*_SYSTEM_DEFAULT?。在這種情況下,將應(yīng)用 XML 值(或在沒有 XML 值的情況下應(yīng)用 Fast DDS 默認(rèn)值)。這意味著,如果?rmw_qos_profile_t?中的任何 QoS 設(shè)置為?*_SYSTEM_DEFAULT?以外的值,則 XML 中的相應(yīng)值將被忽略。

d163218813629388980470c8183c57a2.png

使用其他 FastDDS 功能與 XML

雖然我們創(chuàng)建了一個具有不同配置的兩個發(fā)布者的節(jié)點(diǎn),但很難檢查它們的行為是否不同。現(xiàn)在已經(jīng)介紹了 XML 配置文件的基礎(chǔ)知識,讓我們使用它們來配置一些對節(jié)點(diǎn)有視覺效果的東西。具體來說,將在一個發(fā)布者上設(shè)置最大匹配訂閱者數(shù)量,在另一個發(fā)布者上設(shè)置分區(qū)定義。請注意,這些只是通過 XML 文件可以調(diào)整的所有配置屬性中的一些非常簡單的示例。請參閱*Fast DDS*文檔https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/xml_configuration.html#xml-profiles 以查看可以通過 XML 文件配置的屬性的完整列表。

b53a3af64a33798028be51944a2e028e.png

限制匹配訂閱者的數(shù)量

將最大數(shù)量的匹配訂閱者添加到?/async_topic?發(fā)布者配置文件。它應(yīng)該看起來像這樣:

<!-- async_topic主題的發(fā)布者配置文件 -->
<publisher profile_name="/async_topic"> <!-- 定義名為/async_topic的發(fā)布者配置文件 --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --><qos> <!-- 定義QoS(服務(wù)質(zhì)量)設(shè)置 --><publishMode> <!-- 定義發(fā)布模式 --><kind>ASYNCHRONOUS</kind> <!-- 設(shè)置發(fā)布模式為異步 --></publishMode></qos><matchedSubscribersAllocation> <!-- 定義匹配訂閱者的分配策略 --><initial>0</initial> <!-- 初始分配的訂閱者數(shù)量為0 --><maximum>1</maximum> <!-- 最大分配的訂閱者數(shù)量為1 --><increment>1</increment> <!-- 每次增加的訂閱者數(shù)量為1 --></matchedSubscribersAllocation>
</publisher>

匹配訂閱者的數(shù)量被限制為一個。

現(xiàn)在打開三個終端,不要忘記源化設(shè)置文件并設(shè)置所需的環(huán)境變量。在第一個終端上運(yùn)行發(fā)布者節(jié)點(diǎn),在另外兩個終端上運(yùn)行訂閱者節(jié)點(diǎn)。您應(yīng)該看到只有第一個訂閱者節(jié)點(diǎn)接收到來自兩個主題的消息。第二個訂閱者節(jié)點(diǎn)無法在?/async_topic?中完成匹配過程,因?yàn)榘l(fā)布者阻止了它,因?yàn)樗呀?jīng)達(dá)到了匹配發(fā)布者的最大數(shù)量。因此,只有來自?/sync_topic?的消息將會在這個第三終端中接收到。

[INFO] [1613127657.088860890] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 18'
[INFO] [1613127657.588896594] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 19'
[INFO] [1613127658.088849401] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 20'

在主題內(nèi)使用分區(qū)

分區(qū)功能可用于控制在同一主題內(nèi)哪些發(fā)布者和訂閱者交換信息。

分區(qū)在由域 ID 引起的物理隔離內(nèi)引入了邏輯實(shí)體隔離級別的概念。為了使發(fā)布者與訂閱者進(jìn)行通信,他們必須至少屬于一個共同的分區(qū)。分區(qū)代表了在域和主題之外分離發(fā)布者和訂閱者的另一個級別。與域和主題不同,一個端點(diǎn)可以同時屬于多個分區(qū)。為了在不同的域或主題上共享某些數(shù)據(jù),每個域或主題必須有一個不同的發(fā)布者,分享其自己的更改歷史。然而,單個發(fā)布者可以使用單個主題數(shù)據(jù)更改在不同的分區(qū)上共享相同的數(shù)據(jù)樣本,從而減少網(wǎng)絡(luò)過載。

讓我們將?/sync_topic?發(fā)布者更改為分區(qū)?part1?,并創(chuàng)建一個使用分區(qū)?part2?的新?/sync_topic?訂閱者。他們的配置文件現(xiàn)在應(yīng)如下所示:

<!-- sync_topic主題的發(fā)布者配置文件 -->
<publisher profile_name="/sync_topic"> <!-- 定義一個發(fā)布者配置文件,名稱為/sync_topic --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --><qos> <!-- 定義QoS(服務(wù)質(zhì)量)設(shè)置 --><publishMode> <!-- 定義發(fā)布模式 --><kind>SYNCHRONOUS</kind> <!-- 設(shè)置發(fā)布模式為同步 --></publishMode><partition> <!-- 定義分區(qū) --><names> <!-- 分區(qū)名稱 --><name>part1</name> <!-- 設(shè)置分區(qū)名稱為part1 --></names></partition></qos>
</publisher><!-- sync_topic主題的訂閱者配置文件 -->
<subscriber profile_name="/sync_topic"> <!-- 定義一個訂閱者配置文件,名稱為/sync_topic --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy> <!-- 設(shè)置歷史內(nèi)存策略為動態(tài) --><qos> <!-- 定義QoS(服務(wù)質(zhì)量)設(shè)置 --><partition> <!-- 定義分區(qū) --><names> <!-- 分區(qū)名稱 --><name>part2</name> <!-- 設(shè)置分區(qū)名稱為part2 --></names></partition></qos>
</subscriber>

打開兩個終端。不要忘記加載設(shè)置文件并設(shè)置所需的環(huán)境變量。在第一個終端上運(yùn)行發(fā)布者節(jié)點(diǎn),在另一個終端上運(yùn)行訂閱者節(jié)點(diǎn)。您應(yīng)該看到只有?/async_topic?消息到達(dá)訂閱者。?/sync_topic?訂閱者沒有接收到數(shù)據(jù),因?yàn)樗c相應(yīng)的發(fā)布者在不同的分區(qū)中。

[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'
[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'
[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12'

配置服務(wù)和客戶端

服務(wù)和客戶端各有一個發(fā)布者和一個訂閱者,它們通過兩個不同的主題進(jìn)行通信。例如,對于名為?ping?的服務(wù),有:

  • 在?/rq/ping?上監(jiān)聽請求的服務(wù)訂閱者。

  • 服務(wù)發(fā)布者在?/rr/ping?上發(fā)送響應(yīng)。

  • 客戶端發(fā)布者在?/rq/ping?上發(fā)送請求。

  • 一個客戶端訂閱者正在監(jiān)聽?/rr/ping?上的響應(yīng)。

盡管您可以使用這些主題名稱在 XML 上設(shè)置配置文件,有時您可能希望將相同的配置文件應(yīng)用于節(jié)點(diǎn)上的所有服務(wù)或客戶端。與其為所有服務(wù)生成的所有主題名稱復(fù)制相同的配置文件,您可以只創(chuàng)建一個名為?service?的發(fā)布者和訂閱者配置文件對。對于創(chuàng)建名為?client?的對的客戶端,也可以這樣做。

使用服務(wù)和客戶端創(chuàng)建節(jié)點(diǎn)

開始使用該服務(wù)創(chuàng)建節(jié)點(diǎn)。在您的包中添加一個名為?src/ping_service.cpp?的新源文件,并包含以下內(nèi)容:

#include <memory> // 包含用于智能指針的頭文件#include "rclcpp/rclcpp.hpp" // 包含ROS 2的C++客戶端庫
#include "example_interfaces/srv/trigger.hpp" // 包含example_interfaces包中的Trigger服務(wù)/*** 服務(wù)操作:響應(yīng)success=true并在控制臺打印請求*/
void ping(const std::shared_ptr<example_interfaces::srv::Trigger::Request> request,std::shared_ptr<example_interfaces::srv::Trigger::Response> response)
{// 請求數(shù)據(jù)未使用(void) request;// 構(gòu)建響應(yīng)response->success = true;// 記錄到控制臺RCLCPP_INFO(rclcpp::get_logger("ping_server"), "Incoming request"); // 打印收到請求的日志RCLCPP_INFO(rclcpp::get_logger("ping_server"), "Sending back response"); // 打印發(fā)送響應(yīng)的日志
}int main(int argc, char **argv) // 主函數(shù)
{rclcpp::init(argc, argv); // 初始化ROS 2// 創(chuàng)建節(jié)點(diǎn)和服務(wù)std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("ping_server"); // 創(chuàng)建名為ping_server的節(jié)點(diǎn)rclcpp::Service<example_interfaces::srv::Trigger>::SharedPtr service =node->create_service<example_interfaces::srv::Trigger>("ping", &ping); // 創(chuàng)建名為ping的服務(wù),并綁定到ping函數(shù)// 記錄服務(wù)已準(zhǔn)備好的日志RCLCPP_INFO(rclcpp::get_logger("ping_server"), "Ready to serve."); // 打印服務(wù)已準(zhǔn)備好的日志// 運(yùn)行節(jié)點(diǎn)rclcpp::spin(node); // 運(yùn)行節(jié)點(diǎn)rclcpp::shutdown(); // 關(guān)閉ROS 2
}

在名為?src/ping_client.cpp?的文件中創(chuàng)建客戶端,內(nèi)容如下:

#include <chrono> // 包含用于時間操作的頭文件
#include <memory> // 包含用于智能指針的頭文件#include "rclcpp/rclcpp.hpp" // 包含ROS 2的C++客戶端庫
#include "example_interfaces/srv/trigger.hpp" // 包含example_interfaces包中的Trigger服務(wù)using namespace std::chrono_literals; // 使用chrono命名空間中的字面量int main(int argc, char **argv) // 主函數(shù)
{rclcpp::init(argc, argv); // 初始化ROS 2// 創(chuàng)建節(jié)點(diǎn)和客戶端std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("ping_client"); // 創(chuàng)建名為ping_client的節(jié)點(diǎn)rclcpp::Client<example_interfaces::srv::Trigger>::SharedPtr client =node->create_client<example_interfaces::srv::Trigger>("ping"); // 創(chuàng)建名為ping的客戶端// 創(chuàng)建請求auto request = std::make_shared<example_interfaces::srv::Trigger::Request>(); // 創(chuàng)建Trigger服務(wù)的請求// 等待服務(wù)可用while (!client->wait_for_service(1s)) { // 每隔1秒檢查一次服務(wù)是否可用if (!rclcpp::ok()) { // 如果ROS 2被中斷RCLCPP_ERROR(rclcpp::get_logger("ping_client"), "Interrupted while waiting for the service. Exiting."); // 打印錯誤日志return 0; // 返回0表示程序正常結(jié)束}RCLCPP_INFO(rclcpp::get_logger("ping_client"), "Service not available, waiting again..."); // 打印服務(wù)不可用的日志}// 現(xiàn)在服務(wù)可用了,發(fā)送請求RCLCPP_INFO(rclcpp::get_logger("ping_client"), "Sending request"); // 打印發(fā)送請求的日志auto result = client->async_send_request(request); // 異步發(fā)送請求// 等待結(jié)果并將其記錄到控制臺if (rclcpp::spin_until_future_complete(node, result) ==rclcpp::FutureReturnCode::SUCCESS) // 如果成功接收到響應(yīng){RCLCPP_INFO(rclcpp::get_logger("ping_client"), "Response received"); // 打印接收到響應(yīng)的日志} else {RCLCPP_ERROR(rclcpp::get_logger("ping_client"), "Failed to call service ping"); // 打印調(diào)用服務(wù)失敗的日志}rclcpp::shutdown(); // 關(guān)閉ROS 2return 0; // 返回0表示程序正常結(jié)束
}

打開?CMakeLists.txt?文件并添加兩個新的可執(zhí)行文件?ping_service?和?ping_client?:

find_package(example_interfaces REQUIRED) # 查找example_interfaces包,標(biāo)記為必需add_executable(ping_service src/ping_service.cpp) # 添加可執(zhí)行文件ping_service,源文件為src/ping_service.cpp
ament_target_dependencies(ping_service example_interfaces rclcpp) # 設(shè)置ping_service的依賴項(xiàng)為example_interfaces和rclcppadd_executable(ping_client src/ping_client.cpp) # 添加可執(zhí)行文件ping_client,源文件為src/ping_client.cpp
ament_target_dependencies(ping_client example_interfaces rclcpp) # 設(shè)置ping_client的依賴項(xiàng)為example_interfaces和rclcppinstall(TARGETS # 安裝目標(biāo)ping_service # 安裝ping_serviceDESTINATION lib/${PROJECT_NAME}) # 安裝路徑為lib/${PROJECT_NAME}install(TARGETS # 安裝目標(biāo)ping_client # 安裝ping_clientDESTINATION?lib/${PROJECT_NAME})?#?安裝路徑為lib/${PROJECT_NAME}

最后,構(gòu)建包。

為服務(wù)和客戶端創(chuàng)建 XML 配置文件

創(chuàng)建一個名為?ping.xml?的文件,并包含以下內(nèi)容:

<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"><!-- 默認(rèn)發(fā)布者配置文件 --><publisher profile_name="default_publisher" is_default_profile="true"><!-- 歷史內(nèi)存策略設(shè)置為動態(tài) --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy></publisher><!-- 默認(rèn)訂閱者配置文件 --><subscriber profile_name="default_subscriber" is_default_profile="true"><!-- 歷史內(nèi)存策略設(shè)置為動態(tài) --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy></subscriber><!-- 服務(wù)發(fā)布者配置為同步模式 --><publisher profile_name="service"><!-- 歷史內(nèi)存策略設(shè)置為動態(tài) --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy><qos><publishMode><!-- 發(fā)布模式設(shè)置為同步 --><kind>SYNCHRONOUS</kind></publishMode></qos></publisher><!-- 客戶端發(fā)布者配置為異步模式 --><publisher profile_name="client"><!-- 歷史內(nèi)存策略設(shè)置為動態(tài) --><historyMemoryPolicy>DYNAMIC</historyMemoryPolicy><qos><publishMode><!-- 發(fā)布模式設(shè)置為異步 --><kind>ASYNCHRONOUS</kind></publishMode></qos></publisher></profiles>

此配置文件將服務(wù)上的發(fā)布模式設(shè)置為?SYNCHRONOUS?,將客戶端上的發(fā)布模式設(shè)置為?ASYNCHRONOUS?。請注意,我們僅定義了服務(wù)和客戶端的發(fā)布者配置文件,但也可以提供訂閱者配置文件。

執(zhí)行節(jié)點(diǎn)

打開兩個終端,并在每個終端上加載設(shè)置文件。然后設(shè)置加載 XML 所需的環(huán)境變量:

export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export RMW_FASTRTPS_USE_QOS_FROM_XML=1
export FASTRTPS_DEFAULT_PROFILES_FILE=~/ros2_ws/src/sync_async_node_example_cpp/ping.xml

在第一個終端上運(yùn)行服務(wù)節(jié)點(diǎn)。

ros2 run sync_async_node_example_cpp ping_service

您應(yīng)該看到服務(wù)正在等待請求:

[INFO] [1612977403.805799037] [ping_server]: Ready to serve.

在第二個終端上運(yùn)行客戶端節(jié)點(diǎn)。

ros2 run sync_async_node_example_cpp ping_client

您應(yīng)該看到客戶端發(fā)送請求并接收響應(yīng):

[INFO] [1612977404.805799037] [ping_client]: Sending request
[INFO] [1612977404.825473835] [ping_client]: Response received

同時,服務(wù)器控制臺中的輸出已更新:

[INFO] [1612977403.805799037] [ping_server]: Ready to serve.
[INFO] [1612977404.807314904] [ping_server]: Incoming request
[INFO] [1612977404.836405125] [ping_server]: Sending back response

0913e1ab977a79cb45f4e722dd25d82c.png

http://m.aloenet.com.cn/news/28538.html

相關(guān)文章:

  • 容桂網(wǎng)站制作咨詢企業(yè)查詢官網(wǎng)
  • 手機(jī)端做網(wǎng)站軟件文大俠seo
  • b2c平臺網(wǎng)站建設(shè)比百度好用的搜索軟件手機(jī)版
  • 上傳圖片做網(wǎng)站維護(hù)長春seo網(wǎng)站管理
  • 網(wǎng)站建設(shè)違約責(zé)任今日短新聞20條
  • 做美食推廣的網(wǎng)站朝陽區(qū)搜索優(yōu)化seosem
  • 寧波網(wǎng)站建設(shè)公司軟文范例大全1000字
  • 大連企業(yè)做網(wǎng)站最新軍事新聞 今日 最新消息
  • 婚戀網(wǎng)站女孩子做美容安卓優(yōu)化大師官方版
  • 保定定興網(wǎng)站建設(shè)對百度競價排名的看法
  • 織夢的手機(jī)端網(wǎng)站網(wǎng)站開發(fā)的步驟
  • 食品網(wǎng)站建設(shè)策劃書百度問答庫
  • 網(wǎng)站沒有備案可以做百度推廣嗎最吸引人的引流話術(shù)
  • 青島網(wǎng)站運(yùn)營推廣關(guān)鍵詞排名方案
  • 合肥建站平臺windows優(yōu)化大師官方免費(fèi)
  • html網(wǎng)站開發(fā)中的應(yīng)用百度高級搜索
  • 濟(jì)南網(wǎng)站設(shè)計建設(shè)公司百度營銷推廣登錄平臺
  • 建設(shè)資格執(zhí)業(yè)注冊中心網(wǎng)站長沙seo網(wǎng)絡(luò)推廣
  • 網(wǎng)站上的搜索怎么做青島網(wǎng)站快速排名提升
  • 網(wǎng)站建設(shè)周期重慶seo網(wǎng)絡(luò)推廣關(guān)鍵詞
  • swf做網(wǎng)站頭網(wǎng)絡(luò)促銷
  • 知名商城網(wǎng)站建設(shè)公司seo搜狗
  • 東莞設(shè)計網(wǎng)站長沙網(wǎng)站優(yōu)化推廣
  • 17網(wǎng)站一起做網(wǎng)店 每日新款網(wǎng)站免費(fèi)推廣網(wǎng)站
  • 高州做網(wǎng)站seo咨詢茂名
  • 可以免費(fèi)建手機(jī)網(wǎng)站seo優(yōu)化網(wǎng)站
  • 最新網(wǎng)站源碼營銷網(wǎng)站建設(shè)方案
  • 武漢市網(wǎng)站制作寧波seo推廣咨詢
  • 網(wǎng)站制作要多少錢線上營銷工具
  • 有域名自己做網(wǎng)站嗎網(wǎng)絡(luò)推廣長沙網(wǎng)絡(luò)推廣