ROS2編程基礎課程–Component

  • 2019 年 10 月 5 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/ZhangRelay/article/details/100773710

Composing multiple nodes in a single process

在單個進程中組合多個節點

ROS 1 – Nodes vs. Nodelets ROS 1 -節點與Nodelets

In ROS 1 you can write your code either as a ROS node or as a ROS nodelet. ROS 1 nodes are compiled into executables. ROS 1 nodelets on the other hand are compiled into a shared library which is then loaded at runtime by a container process.

在ROS 1,無論是作為一個ROS節點或作為ROS nodelet都可以通過程式碼實現。ROS 1節點被編譯成可執行文件。另一方面,ROS 1 nodelets被編譯成共享庫,然後由容器進程在運行時載入。

ROS 2 – Unified API ROS 2 – 統一API

In ROS 2 the recommended way of writing your code is similar to a nodelet – we call it a Component. This makes is easy to add common concepts to existing code, like a life cycle. The biggest drawback of different APIs is avoided in ROS 2 since both approaches use the same API in ROS 2.

在ROS 2中,編寫程式碼的推薦方法類似於nodelet – 我們稱之為Component。這樣可以很容易地將常見概念添加到現有程式碼中,例如生命周期。ROS 2中避免了不同API的最大缺點,因為這兩種方法在ROS 2中使用相同的API。

Note 注意

It is still possible to use the node-like style of 「writing your own main」 but for the common case it is not recommended.

仍然可以使用類似節點的「編寫自定義main」樣式,但對於常見情況,不推薦使用。

By making the process layout a deploy-time decision the user can choose between:

通過使流程布局成為部署時決策,用戶可以選擇:

  • running multiple nodes in separate processes with the benefits of process/fault isolation as well as easier debugging of individual nodes and

在單獨的進程中運行多個節點,具有進程/故障隔離的好處,以及更容易調試單個節點和

  • running multiple nodes in a single process with the lower overhead and optionally more efficient communication (see Intra Process Communication).

在單個進程中運行多個節點,具有較低的開銷和可選的更高效的通訊(請參考進程內通訊)。

Additionally ros2 launch can be used to automate these actions through specialized launch actions.

此外,ros2 launch還可用於通過專門的啟動操作自動執行這些操作。

Writing a Component 編寫組件

Since a component is only built into a shared library it doesn』t have a main function (see Talker source code). A component is commonly a subclass of rclcpp::Node. Since it is not in control of the thread it shouldn』t perform any long running or blocking tasks in its constructor. Instead it can use timers to get periodic notification. Additionally it can create publishers, subscribers, servers, and clients.

由於組件僅編譯在共享庫中,因此它沒有main函數(請參考Talker源程式碼)。組件通常是子類rclcpp::Node。由於它不受執行緒控制,因此不應在其構造函數中執行任何長時間運行或阻塞任務。相反,它可以使用計時器來獲得定期通知。此外,它還可以創建發布器,訂閱器,伺服器和客戶端。

An important aspect of making such a class a component is that the class registers itself using macros from the package rclcpp_components (see the last line in the source code). This makes the component discoverable when its library is being loaded into a running process – it acts as kind of an entry point.

將這樣的類作為組件的一個重要方面是類使用rclcpp_components包中的宏來註冊自己(參考源程式碼中的最後一行)。這使得組件在將其庫載入到正在運行的進程時可被發現 – 它充當入口點。

Additionally, once a component is created, it must be registered with the index to be discoverable by the tooling.

此外,一旦創建了組件,就必須將其註冊到工具可以發現的索引。

add_library(talker_component SHARED

src/talker_component.cpp)

rclcpp_components_register_nodes(talker_component "composition::Talker")

# To register multiple components in the same shared library, use multiple calls# rclcpp_components_register_nodes(talker_component "composition::Talker2")

Note 注意

In order for the component_container to be able to find desired components, it must be executed or launched from a shell that has sourced the corresponding workspace.

為了使component_container能夠找到所需的組件,必須從已獲取相應工作空間的shell執行或啟動它。

Using Components 使用組件

The composition package contains a couple of different approaches on how to use components. The three most common ones are:

組合包中包含了一些關於如何使用的組件不同的方法。最常見的三種是:

  • Start a (generic container process) and call the ROS service load_node offered by the container. The ROS service will then load the component specified by the passed package name and library name and start executing it within the running process. Instead of calling the ROS service programmatically you can also use a command line tool to invoke the ROS service with the passed command line arguments

啟動(通用容器進程)並調用容器提供的ROS服務load_node。然後,ROS服務將載入由傳遞的包名和庫名 指定的組件,並在運行的進程中開始執行它。您不必以編程方式調用ROS服務,也可以使用命令行工具使用 傳遞的命令行參數調用ROS服務

  • Create a custom executable containing multiple nodes which are known at compile time. This approach requires that each component has a header file (which is not strictly needed for the first case).

創建包含在編譯時已知的多個節點的自定義可執行文件。這種方法要求每個組件都有一個頭文件(第一種情況 並不嚴格需要)。

  • Create a launch file and use ros2 launch to create a container process with multiple components loaded.

創建啟動文件並用ros2 launch創建載入了多個組件的容器進程。

Run the demos 運行演示

The demos use executables from rclcpp_components, ros2component, and composition packages, and can be run with the following commands.

演示使用來自rclcpp_componentsros2componentcomposition包的可執行文件,並且可以使用以下命令運行。

Discover available components 發現可用的組件

To see what components are registered and available in the workspace, execute the following in a shell:

要查看工作區中註冊和可用的組件,請在shell中執行以下操作:

$ ros2 component types

composition

composition::Talker

composition::Listener

composition::Server

composition::Client

Run-time composition using ROS services (1.) with a publisher and subscriber

使用ROS服務(1.)與發布器和訂閱器的運行時組合

In the first shell, start the component container:

在第一個shell中,啟動組件容器:

ros2 run rclcpp_components component_container

Verify that the container is running via ros2 command line tools:

通過ros2命令行工具驗證容器是否正在運行:

$ ros2 component list

/ComponentManager

In the second shell (see talker source code). The command will return the unique ID of the loaded component as well as the node name.

在第二個shell中(參考talker源程式碼)。該命令將返回已載入組件的唯一ID以及節點名稱。

$ ros2 component load /ComponentManager composition composition::Talker

Loaded component 1 into '/ComponentManager' container node as '/talker'

Now the first shell should show a message that the component was loaded as well as repeated message for publishing a message.

現在,第一個shell應顯示已載入組件的消息以及用於發布消息的重複消息。

Another command in the second shell (see listener source code):

第二個shell中的另一個命令(參考監聽器源程式碼):

$ ros2 component load /ComponentManager composition composition::Listener

Loaded component 2 into '/ComponentManager' container node as '/listener'

The ros2 command line utility can now be used to inspect the state of the container:

該ros2命令行實用程式現在可以用於檢查容器的狀態:

$ ros2 component list

/ComponentManager

1 /talker

2 /listener

Now the first shell should show repeated output for each received message.

現在,第一個shell應該顯示每個收到的消息的重複輸出。

Run-time composition using ROS services (1.) with a server and client

使用ROS服務(1.)與伺服器和客戶端的運行時組合

The example with a server and a client is very similar. 伺服器和客戶端的示例非常相似。

In the first shell: 在第一個shell中:

ros2 run rclcpp_components component_container

In the second shell (see server and client source code): 在第二個shell中(請參考伺服器客戶端源程式碼):

ros2 component load /ComponentManager composition composition::Server

ros2 component load /ComponentManager composition composition::Client

In this case the client sends a request to the server, the server processes the request and replies with a response, and the client prints the received response.

在這種情況下,客戶端向伺服器發送請求,伺服器處理請求並回復響應,客戶端列印接收到的響應。

Compile-time composition using ROS services (2.)

使用ROS服務編譯時組成(2.)

This demos shows that the same shared libraries can be reused to compile a single executable running multiple components. The executable contains all four components from above: talker and listener as well as server and client.

此演示顯示可以重用相同的共享庫來編譯運行多個組件的單個可執行文件。可執行文件包含上面的所有四個組件:talker和listener以及伺服器和客戶端。

In the shell call (see source code):

在shell調用中(參考源程式碼):

ros2 run composition manual_composition

This should show repeated messages from both pairs, the talker and the listener as well as the server and the client.

這應該顯示來自兩個對,發布器和聽眾以及伺服器和客戶端的重複消息。

Note 注意

Manually-composed components will not be reflected in the ros2 component list command line tool output. 手動編寫的組件不會反映在ros2 component list命令行工具輸出中。

Run-time composition using dlopen 使用dlopen運行時組合

This demo presents an alternative to 1. by creating a generic container process and explicitly passing the libraries to load without using ROS interfaces. The process will open each library and create one instance of each 「rclcpp::Node」 class in the library source code).

此演示提供了1的替代方法,通過創建通用容器進程並顯式傳遞庫而不使用ROS介面。該過程將打開每個庫並在庫源程式碼中創建每個「rclcpp :: Node」類的一個實例。

Linux In the shell call: Linux在shell中調用:

ros2 run composition dlopen_composition `ros2 pkg prefix composition`/lib/libtalker_component.so `ros2 pkg prefix composition`/lib/liblistener_component.so

OSX In the shell call:

OSX在shell中調用:

ros2 run composition dlopen_composition `ros2 pkg prefix composition`/lib/libtalker_component.dylib `ros2 pkg prefix composition`/lib/liblistener_component.dylib

Windows In cmd.exe call

Windows在cmd.exe中調用

ros2 pkg prefix composition

to get the path to where composition is installed. Then call

獲取安裝組合的路徑。然後調用:

ros2 run composition dlopen_composition <path_to_composition_install>bintalker_component.dll <path_to_composition_install>binlistener_component.dll

Now the shell should show repeated output for each sent and received message.

現在shell應該為每個發送和接收的消息顯示重複輸出。

Note 注意

dlopen-composed components will not be reflected in the ros2 component list command line tool output.

dlopen組成的組件不會反映在命令行ros2 component list工具輸出中。

Composition using launch actions

使用launch啟動行動的組合

While the command line tools are useful for debugging and diagnosing component configurations, it is frequently more convenient to start a set of components at the same time. To automate this action, we can use the functionality in ros2 launch.

雖然命令行工具對於調試和診斷組件配置很有用,但同時啟動一組組件通常更方便。要自動執行此操作,可以使用ros2 launch功能。

ros2 launch composition composition_demo.launch.py

Advanced Topics 高級主題

Now that we have seen the basic operation of components, we can discuss a few more advanced topics.

現在已經看到了組件的基本操作,我們可以討論一些更高級的主題。

Unloading components 卸載組件

In the first shell, start the component container: 在第一個shell中,啟動組件容器:

ros2 run rclcpp_components component_container

Verify that the container is running via ros2 command line tools: 通過ros2命令行工具驗證容器是否正在運行:

$ ros2 component list

/ComponentManager

In the second shell (see talker source code). The command will return the unique ID of the loaded component as well as the node name.

在第二個shell中(參考talker源程式碼)。該命令將返回已載入組件的唯一ID以及節點名稱。

$ ros2 component load /ComponentManager composition composition::Talker

Loaded component 1 into '/ComponentManager' container node as '/talker'

$ ros2 component load /ComponentManager composition composition::Listener

Loaded component 2 into '/ComponentManager' container node as '/listener'

Use the unique ID to unload the node from the component container.

使用唯一ID從組件容器中卸載節點。

$ ros2 component unload /ComponentManager 1 2

Unloaded component 1 from '/ComponentManager' container

Unloaded component 2 from '/ComponentManager' container

In the first shell, verify that the repeated messages from talker and listener have stopped.

在第一個shell中,驗證來自talker和listener的重複消息是否已停止。

Remapping container name and namespace

重新映射容器名稱和命名空間

The component manager name and namespace can be remapped via standard command line arguments:

可以通過標準命令行參數重新映射組件管理器名稱和命名空間:

ros2 run rclcpp_components component_container __node:=MyContainer __ns:=/ns

In a second shell, components can be loaded by using the updated container name:

在第二個shell中,可以使用更新的容器名稱載入組件:

ros2 component load /ns/MyContainer composition composition::Listener

Note 注意

Namespace remappings of the container do not affect loaded components.

容器的命名空間重映射不會影響已載入的組件。

Remap component names and namespaces

重新映射組件名稱和命名空間

Component names and namespaces may be adjusted via arguments to the load command.

組件名稱和名稱空間可以通過load命令的參數進行調整。

In the first shell, start the component container:

在第一個shell中,啟動組件容器:

ros2 run rclcpp_components component_container

Some examples of how to remap names and namespaces:

有關如何重新映射名稱和名稱空間的一些示例:

# Remap node name

ros2 component load /ComponentManager composition composition::Talker –node-name talker2

# Remap namespace

ros2 component load /ComponentManager composition composition::Talker –node-namespace /ns

# Remap both

ros2 component load /ComponentManager composition composition::Talker –node-name talker3 –node-namespace /ns2

The corresponding entries appear in ros2 component list:

ros2 component list相應的條目顯示在:

$ ros2 component list

/ComponentManager

1 /talker2

2 /ns/talker

3 /ns2/talker3

Note 注意

Namespace remappings of the container do not affect loaded components.

容器的命名空間重映射不會影響已載入的組件。