ROS2 高度なインターフェースとミドルウェア

10 TF2 座標変換

10 TF2 座標変換(TF2 Transform)

10.1 TF2 概要

10.1.1 TF2 とは

TF2(Transform 2)は、座標変換を管理するために ROS 2 で使用されるライブラリです。複数の座標系間の関係を追跡し、開発者が異なる座標系間でデータ(例えば、点、ベクトル、姿勢)を変換できるようにします。

10.1.2 TF2 の使用

適用注釈
センサー統合異なるセンサーからのデータを統一座標系に変換
ナビゲーション地図座標系をロボット座標系に変換
機械アームベースに対するエンドエフェクターの姿勢を計算
可視化RViz2 でロボットの状態を正しく表示

10.1.3 座標系の指定

名前目的
Mapグローバル/世界座標、固定
odom位置決め用の走行距離座標系
base_linkロボットベース座標系
base_footprint地面に投影されたロボットシャーシ
Camera_linkカメラ座標系
Laser_linkレーザーレーダー座標系

23. ROS2 TF2 座標変換

TF2 紹介

座標系は非常に馴染みのある概念で、ロボティクスにおける重要な基盤です。完全なロボットシステムには多くの座標系があります。これらの座標の位置はどのように管理する必要がありますか?ROS は座標管理者 TF2 を提供しました。

2. ロボットの座標系

座標系は移動ロボットシステムでも同様に重要です。例えば、移動ロボットの中心点は base_link、レーダーの位置はレーダー座標系 laser_link と呼ばれ、ロボットが移動する場所の累積メトル平方は odom と呼ばれ、累積誤差とドリフトを持ち、絶対位置は地図座標 Map と呼ばれます。

座標の 1 つの層の関係は複雑で、いくつかは比較的固定され、いくつかは絶え間なく変化しています。一見シンプルな座標は空間内で複雑になり、優れた座標系システムは特に重要です。

ROS の TF 関数の基本原理は、これらの数学的変換をカプセル化することです。詳細な理論的知識はすべてのロボティクスのカリキュラムで利用可能です。主に TF 座標管理システムの使用方法を説明します。

3 TF コマンドラインの操作

2 匹のカメの例から始めて、座標に基づくロボットの計算について学びましょう。

3.1. ツールのインストール

bash
sudo apt install ros-${ROS_DISTRO}-turtle-tf2-py ros-humble-tf2-tools
sudo pip3 install transforms3d
sudo apt install ros-${ROS_DISTRO}-rqt-tf-tree

3.2. 起動

bash
# ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py
ros2 run turtlesim turtle_teleop_key

3.3. TF ツリーの表示

bash
ros2 run rqt_tf_tree rqt_tf_tree

3.4. 座標変換情報の問い合わせ

bash
ros2 run tf2_ros tf2_echo turtle2 turtle1

3.5. 座標の可視化

bash
rviz2

4. 静的座標変換

4.1. A から B への位置の配信

bash
ros2 run tf2_ros static_transform_publisher 0 0 3 0 0 3.14 A B

4.2. TF 関係の取得/参照

bash
ros2 run tf2_ros tf2_echo A B

4.3. rivz 可視化

bash
rviz2

5. ケースの提示

7. 新機能パッケージ

bash
ros2 pkg create pkg_tf --build-type ament_python --dependencies rclpy --node-name turtle_tf_broadcaster
bash
import math
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import TransformStamped
from tf2_ros import TransformBroadcaster
from turtlesim.msg import Pose

def quaternion_from_euler(roll, pitch, yaw):
  cy = math.cos(yaw * 0.5)
  sy = math.sin(yaw * 0.5)
  cp = math.cos(pitch * 0.5)
  sp = math.sin(pitch * 0.5)
  cr = math.cos(roll * 0.5)
  sr = math.sin(roll * 0.5)

  w = cr * cp * cy + sr * sp * sy
  x = sr * cp * cy - cr * sp * sy
  y = cr * sp * cy + sr * cp * sy
  z = cr * cp * sy - sr * sp * cy

  return (x, y, z, w)

class TurtleTFBroadcaster(Node):
  def __init__(self, name):
  super().__init__(name)
  self.turtlename = self.declare_parameter('turtlename', 'turtle').value
  self.tf_broadcaster = TransformBroadcaster(self)
  self.subscription = self.create_subscription(
  Pose,
  f'/{self.turtlename}/pose',
  self.turtle_pose_callback, 1)

  def turtle_pose_callback(self, msg):
  transform = TransformStamped()
  transform.header.stamp = self.get_clock().now().to_msg()
  transform.header.frame_id = 'world'
  transform.child_frame_id = self.turtlename
  transform.transform.translation.x = msg.x
  transform.transform.translation.y = msg.y
  transform.transform.translation.z = 0.0
  q = quaternion_from_euler(0, 0, msg.theta)
  transform.transform.rotation.x = q[0]
  transform.transform.rotation.y = q[1]
  transform.transform.rotation.z = q[2]
  transform.transform.rotation.w = q[3]

  self.tf_broadcaster.sendTransform(transform)

def main(args=None):
  rclpy.init(args=args)
  node = TurtleTFBroadcaster("turtle_tf_broadcaster")
  rclpy.spin(node)
  node.destroy_node()
  rclpy.shutdown()
python
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

def generate_launch_description():
  return LaunchDescription([
  DeclareLaunchArgument('source_frame', default_value='turtle1', description='Target frame name.'),
  Node(package='turtlesim', executable='turtlesim_node'),
  Node(package='pkg_tf', executable='turtle_tf_broadcaster',
  name='broadcaster1', parameters=[{'turtlename': 'turtle1'}]),
  Node(package='pkg_tf', executable='turtle_tf_broadcaster',
  name='broadcaster2', parameters=[{'turtlename': 'turtle2'}]),
  Node(package='pkg_tf', executable='turtle_following',
  name='listener', parameters=[{'source_frame': LaunchConfiguration('source_frame')}]),
  ])

8. 設定ファイルの編集

bash
import os
from glob import glob
bash
(os.path.join('share',package_name,'launch'),glob('launch/*')),

9. 機能パッケージのコンパイル

bash
colcon build --packages-select pkg_tf

操作手順

bash
# source install/setup.bash
ros2 launch pkg_tf turtle_following.launch.py
bash
ros2 run turtlesim turtle_teleop_key

カスタムインターフェースメッセージ

11 カスタムインターフェースメッセージ

ROS システムでは、Topic、Service、Action の 3 つの通信メカニズムはすべてコア概念であるコミュニケーションインターフェースに依存しています。

通信の本質は、複数の当事者間の情報交換であり、一方通行の自己表現ではありません。効率的で信頼性の高い相互作用を実現するために、通信に関与するノードはデータの形式と意味について共通の理解を持っている必要があります。このため、ROS は標準化された通信インターフェースを導入し、すべての種類のメッセージに明確で調和の取れたデータ構造を定義しています。

ROS は 3 つの一般的な通信メカニズムを持っています:topics、services、actions。各定義されたインターフェースを通じて、さまざまなノードが有機的にリンクされます。

11.1 カスタムインターフェース作成プロセス

主なステップは次のとおりです:

インターフェース機能パッケージの作成

.msg ファイル、.srv ファイル、.action ファイルの作成と編集

設定ファイルの編集

コンパイル

テスト

11.2 アクション通信用のカスタムインターフェースを作成

11.3 トピック通信用のカスタムインターフェースを作成

bash
string  name
int32  age
float64  height
bash
# CMakeLists.txt
rosidl_generate_interfaces(${PROJECT_NAME}
  "action/Progress.action"
  "msg/Person.msg"
)
bash
# package.xml
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>action_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
bash
cd ~/workspace
colcon build --packages-select pkg_interfaces
bash
ros2 interface show pkg_interfaces/msg/Person

11.4 サービス通信用のカスタムインターフェースを作成

bash
int32 num1
int32 num2
---
int32 sum
bash
rosidl_generate_interfaces(${PROJECT_NAME}
  "action/Progress.action"
  "msg/Person.msg"
  "srv/Add.srv"
)
bash
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>action_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
bash
cd ~/workspace
colcon build --packages-select pkg_interfaces
source install/setup.bash
bash
ros2 interface show pkg_interfaces/srv/Add

11.5 次のステップ

1.12 パラメータサービスケース

2.13 メタファンクションパッケージ

12 パラメータサービスケース

12 パラメータサービス(Parameters)

12.1 パラメータの概要

ROS ロボットシステムにおいて、パラメータは C++ グローバル変数として機能し、複数のノードに簡単なデータ共有メカニズムを提供します。これらのパラメータは、グローバル辞書の形式でシステムに格納されます。

12.2 小さなカメの定例におけるパラメータ

bash
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key
bash
ros2 param list
bash
ros2 param describe turtlesim background_b
ros2 param get turtlesim background_b
ros2 param set turtlesim background_b 10
bash
ros2 param dump turtlesim >> turtlesim.yaml
ros2 param load turtlesim turtlesim.yaml

12.3 パラメータケース

12.3.1 新機能パッケージ

bash
ros2 pkg create pkg_param --build-type ament_python --dependencies rclpy --node-name param_demo

12.3.2 コードの実現

bash
import rclpy
from rclpy.node import Node

class ParameterNode(Node):
  def __init__(self, name):
  super().__init__(name)
  self.timer = self.create_timer(2.0, self.timer_callback)
  self.declare_parameter('robot_name', 'muto')

  def timer_callback(self):
  robot_name_param = self.get_parameter('robot_name').get_parameter_value().string_value
  self.get_logger().info('Hello %s!' % robot_name_param)

def main(args=None):
  rclpy.init(args=args)
  node = ParameterNode("param_declare")
  rclpy.spin(node)
  node.destroy_node()
  rclpy.shutdown()

12.3.3 機能パッケージのコンパイル

bash
colcon build --packages-select pkg_param

12.3.4 操作手順

bash
# source install/setup.bash
ros2 run pkg_param param_demo
bash
ros2 param set param_declare robot_name robot

12.4 次のステップ

1.13 メタファンクションパッケージ

2.14 分散通信

13 メタパック

13 メタパッケージ(Metapackages)

13.1 メタファンクションパッケージの概要

13.1.1 メタファンクショナルキットとは

ROS2 では、完全な機能モジュールは多くの機能パッケージで構成されることが多いです。例えばロボットナビゲーションでは、このモジュールには通常、地図サービス、位置決めアルゴリズム、経路計画、運動制御などの複数のサブ機能パッケージが含まれます。

bash
sudo apt install ros-humble-desktop

13.1.2 メタファンクションパッケージの役割

目的注釈
組織関連する機能パッケージをグループ化
簡素化されたインストール一度に複数のパッケージのインストール
依存関係管理統合された依存関係管理
ドキュメント明確なプロジェクト構造
バージョン管理バージョンの統合された配信と管理

13.2 実装ケース

bash
ros2 pkg create pkg_metapackage
bash
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>pkg_metapackage</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="1461190907@qq.com">root</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <exec_depend>pkg_interfaces</exec_depend>
  <exec_depend>pkg_helloworld_py</exec_depend>
  <exec_depend>pkg_topic</exec_depend>
  <exec_depend>pkg_service</exec_depend>
  <exec_depend>pkg_action</exec_depend>
  <exec_depend>pkg_param</exec_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
  <build_type>ament_cmake</build_type>
  </export>
</package>
bash
cmake_minimum_required(VERSION 3.5)
project(pkg_metapackage)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)

ament_package()
bash
colcon build --packages-select pkg_metapackage

13.3 次のステップ

1.14 分散通信 - 分散通信を学ぶ

DDS - DDS 中間体を学ぶ

14 分散通信

14 分散通信

14.1 分散通信の概要

ROS2 は、便利なホスト間ネットワークデータ相互作用を可能にする強力な分散通信フレームワークです。底辺は DDS(Data Distribution Service)中間体に基づいており、ROS_DOMAIN_ID を介して通信を管理します:異なるデバイスのノードが同じドメイン ID を設定し、同じネットワーク内にある場合、自動的に検出して自由に通信します;反対に、ID は互いに分離されています。

14.1.1 分散通信とは

ROS 2 分散通信は、複数のコンピューターノードが中央サーバーなしで互いに通信できるようにします。これは DDS(Data Distribution Service)を通じて実現されます。

14.1.2 分散通信の特性

特性注釈
中心化されていないROS Master は不要。
自動検出ノードがネットワーク上の他のノードを自動的に見つける
クロスプラットフォーム異なるオペレーティングシステム間の通信
信頼できる転送複数の QoS ポリシーをサポート

14.2 ROS_DOMAIN_ID

14.2.1 ドメイン ID の概念

ROS_DOMAIN_ID は、異なる ROS2 ネットワークを分離するために使用されます。

14.3 達成

14.3.1 デフォルト達成

bash
ros2 run demo_nodes_py talker
ros2 run demo_nodes_py listener

14.3.2 分散ネットワークサブグループ

bash
$ export ROS_DOMAIN_ID=<your_domain_id>

14.3.3 ケース 1

bash
echo "export ROS_DOMAIN_ID=6" >> ~/.bashrc
source ~/.bashrc
ros2 run demo_nodes_py talker
bash
echo "export ROS_DOMAIN_ID=6" >> ~/.bashrc
source ~/.bashrc
ros2 run demo_nodes_py listener

ケース 2

bash
ros2 run turtlesim turtlesim_node
bash
ros2 run turtlesim turtle_teleop_key

14.4 注意

ROS_DOMAIN_ID の値を設定する際、それはランダムではありませんが、拘束力もあります:

推奨 ROS_DOMAIN_ID の値は [0,101] の間で、0 と 101 を含みます。

14.5 DDS ドメイン ID 値の計算規則(レベル知識)

14.6 次のステップ

DDS - DDS 中間体を深く学ぶ

時間関連 API - Time API を学ぶ

https://fast-dds.docs.eprosima.com/en/latest/

15 DDS

15 DDS(Data Distribution Service)

15.1 DDS の概要

15.1.1 DDS とは?

DDS(Data Distribution Service)は、データ中心のパブリッシュ・サブスクライブ中間体標準であり、ROS 2 は DDS を使用してより低レベルの通信を実現します。

15.1.2 DDS コア機能

機能注釈
検出メカニズムネットワーク上の DDS 参加者を自動的に検出
開始/サブスクリプションデータ転送モードを解決
QoS ポリシー利用可能なサービスの品質
タイプシステム強い型のデータ定義
ゼロコピー効率的なデータ転送

15.2 通信モデル

15.3 ROS2 における DDS のアプリケーション

15.4 品質サービス戦略

DDS のもう 1 つのコア機能は、サービス品質戦略:Qos です。

戦略は次のとおりです:

DEADLINE 戦略:各データ通信は所定の期限内に少なくとも 1 回完了する必要があることを示します。

HISTORY ポリシー:過去のデータキャッシュのサイズ制限を示します。

RELIABILITY ポリシー:データ転送の信頼性パターンを表します。

DURABILITY ポリシー:後期到着ノードに履歴データを提供するように構成でき、新しいノードがシステムにより速く入れるようにします。

15.5. テストケース

ケース 1 - 注文ラインで DDS を構成

bash
ros2 topic pub /chatter std_msgs/msg/Int32 "data: 66" --qos-reliability best_effort
bash
ros2 topic echo /chatter --qos-reliability reliable