基本的な ROS メッセージの操作
この例では、ロボティクス アプリケーションで一般に使用される ROS メッセージの作成、検査、取り込みを MATLAB® で行うためのさまざまな方法を示します。
メッセージは、ROS でデータを交換するための主要なコンテナーです。トピックとサービスでは、メッセージを使用してノード間でデータを伝達します。(トピックとサービスの詳細については、ROS のパブリッシャーおよびサブスクライバーとのデータ交換およびCall and Provide ROS Servicesを参照)
前提条件:ROS 入門、ROS ネットワークへの接続
それぞれのメッセージに、そのデータ構造を識別するための "メッセージ タイプ" があります。たとえば、レーザー スキャナーからのセンサー データは、一般に sensor_msgs/LaserScan
タイプのメッセージで送信されます。各メッセージ タイプは、メッセージに含まれているデータ要素を識別します。それぞれのメッセージ タイプの名前は、パッケージ名の後にスラッシュ (/) とタイプ名を組み合わせた名前になります。
メッセージ タイプの特定
ROS マスターとグローバル ノードを初期化します。
rosinit
Launching ROS Core... .Done in 1.0834 seconds. Initializing ROS master on http://172.30.179.123:54319. Initializing global node /matlab_global_node_07475 with NodeURI http://dcc521788glnxa64:43543/ and MasterURI http://localhost:54319.
exampleHelperROSCreateSampleNetwork
を使用して、ROS ネットワークに 3 つのノードとサンプルのパブリッシャーおよびサブスクライバーを追加します。
exampleHelperROSCreateSampleNetwork
このネットワークには、いくつかのトピックと関連するパブリッシャーおよびサブスクライバーをもつさまざまなノードがあります。
使用可能なトピックの完全なリストを確認するには、rostopic
list
を呼び出します。
rostopic list
/pose /rosout /scan /tf
/scan
トピックで送信されるデータのタイプの詳細を確認する場合は、rostopic info
コマンドを使用して調べます。/scan
のメッセージ タイプは sensor_msgs/LaserScan
です。
rostopic info /scan
Type: sensor_msgs/LaserScan Publishers: * /node_3 (http://dcc521788glnxa64:33517/) Subscribers: * /node_1 (http://dcc521788glnxa64:41267/) * /node_2 (http://dcc521788glnxa64:46355/)
コマンドの出力から、トピックをパブリッシュしているノードとサブスクライブしているノードもわかります。パブリッシャーとサブスクライバーの詳細については、Call and Provide ROS Servicesを参照してください。
トピックのメッセージ タイプの詳細を調べるには、関数rosmessage
を使用して同じタイプの空のメッセージを作成します。rosmessage
では、メッセージ タイプのタブ補完がサポートされています。メッセージ タイプの完全な名前を入力するには、目的の名前の最初の数文字を入力して "Tab" キーを押します。
メッセージの作成時や通信時の効率を高めるには、構造体形式でメッセージを使用します。
scandata = rosmessage("sensor_msgs/LaserScan","DataFormat","struct")
scandata = struct with fields:
MessageType: 'sensor_msgs/LaserScan'
Header: [1x1 struct]
AngleMin: 0
AngleMax: 0
AngleIncrement: 0
TimeIncrement: 0
ScanTime: 0
RangeMin: 0
RangeMax: 0
Ranges: [0x1 single]
Intensities: [0x1 single]
作成されたメッセージ scandata
には、レーザー スキャナーから一般に受信するデータに関連する多数のプロパティが含まれています。たとえば、RangeMin
フィールドには最小検出距離、RangeMax
には最大検出距離が格納されます。
トピックとサービスについての使用可能なすべてのメッセージ タイプの完全なリストを確認するには、rosmsg
list
を使用します。
メッセージ構造体の確認とメッセージ データの取得
ROS メッセージは構造体であり、構造体のフィールドにメッセージ データが格納されます。MATLAB には、メッセージの内容を特定して確認できる便利な方法があります。
/pose
トピックをサブスクライブすると、送信されるメッセージを受信して調べることができます。
posesub = rossubscriber("/pose","DataFormat","struct")
posesub = Subscriber with properties: TopicName: '/pose' LatestMessage: [] MessageType: 'geometry_msgs/Twist' BufferSize: 1 MessagePreprocessingEnabled: 0 NewMessageFcn: [] DataFormat: 'struct'
receive
を使用して、サブスクライバーからデータを取得します。新しいメッセージを受信すると、そのメッセージが関数から返されて posedata
変数に格納されます (2 番目の引数はタイムアウトの秒数です)。
posedata = receive(posesub,10)
posedata = struct with fields:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 struct]
Angular: [1x1 struct]
メッセージのタイプは geometry_msgs/Twist
です。メッセージには、このほかに Linear
と Angular
の 2 つのフィールドがあります。それらのメッセージ フィールドに直接アクセスして、それらの値を確認できます。
posedata.Linear
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
X: 0.0315
Y: 0.0406
Z: -0.0373
posedata.Angular
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
X: 0.0413
Y: 0.0132
Z: -0.0402
それらの各メッセージ フィールドの値自体が実際にはメッセージです。それらのメッセージ タイプは geometry_msgs/Vector3
です。geometry_msgs/Twist
は、geometry_msgs/Vector3
の 2 つのメッセージで構成される複合メッセージです。
それらの入れ子になったメッセージのデータ アクセスも、他のメッセージのデータにアクセスする場合とまったく同じです。次のコマンドを使用して Linear
メッセージの X
成分にアクセスします。
xpos = posedata.Linear.X
xpos = 0.0315
メッセージに含まれるすべてのデータの簡単な概要を確認する場合は、関数 rosShowDetails
を呼び出します。rosShowDetails
はいずれのタイプのメッセージに対しても機能し、すべてのメッセージ データ フィールドを再帰的に表示します。
rosShowDetails(posedata)
ans = ' MessageType : geometry_msgs/Twist Linear MessageType : geometry_msgs/Vector3 X : 0.03147236863931789 Y : 0.04057919370756193 Z : -0.03730131837064939 Angular MessageType : geometry_msgs/Vector3 X : 0.04133758561390194 Y : 0.01323592462254095 Z : -0.04024595950005905'
rosShowDetails
は、デバッグ中およびメッセージの内容をすばやく調べたいときに役立ちます。
メッセージ データの設定
メッセージ フィールドの値を設定することもできます。タイプが geometry_msgs/Twist
のメッセージを作成します。
twist = rosmessage("geometry_msgs/Twist","DataFormat","struct")
twist = struct with fields:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 struct]
Angular: [1x1 struct]
このメッセージの数値フィールドは、既定では 0
に初期化されます。このメッセージの任意のプロパティを変更できます。Linear.Y
のエントリを 5
に設定します。
twist.Linear.Y = 5;
メッセージ データを表示して、変更が反映されたことを確認します。
twist.Linear
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
X: 0
Y: 5
Z: 0
メッセージにデータが取り込まれたら、それをパブリッシャー、サブスクライバー、およびサービスで使用できます。ROS のパブリッシャーおよびサブスクライバーとのデータ交換およびCall and Provide ROS Servicesの例を参照してください。
メッセージの保存と読み込み
後で使用するためにメッセージを保存して内容を格納できます。
サブスクライバーから新しいメッセージを取得します。
posedata = receive(posesub,10)
posedata = struct with fields:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 struct]
Angular: [1x1 struct]
MATLAB の関数save
を使用して、姿勢データを MAT ファイルに保存します。
save('posedata.mat','posedata')
ファイルをワークスペースに再度読み込む前に、posedata
変数をクリアします。
clear posedata
これで、関数load
を呼び出してメッセージ データを読み込むことができます。これにより、上記の posedata
が messageData
構造体に読み込まれます。posedata
は struct のデータ フィールドです。
messageData = load('posedata.mat')
messageData = struct with fields:
posedata: [1x1 struct]
messageData.posedata
を調べてメッセージの内容を確認します。
messageData.posedata
ans = struct with fields:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 struct]
Angular: [1x1 struct]
ここで、MAT ファイルは削除できます。
delete('posedata.mat')
メッセージ内の配列
ROS からのメッセージには、他のメッセージに格納されているものや他のメッセージの配列を含むものもあります。
ワークスペースの変数 tf
にサンプルのメッセージが含まれています。(exampleHelperROSCreateSampleNetwork
スクリプトで作成された変数です。)ここでは、座標変換に使用される tf/tfMessage
タイプのメッセージです。
tf
tf = struct with fields:
MessageType: 'tf/tfMessage'
Transforms: [1x53 struct]
tf
には 2 つのフィールドがあり、MessageType
には標準のデータ配列、Transforms
にはオブジェクト配列が含まれています。Transforms
には 53 件のメッセージが格納されており、そのすべてが同じ構造体をもちます。
Transforms
の tf
を展開して構造体を確認します。
tf.Transforms
ans=1×53 struct array with fields:
MessageType
Header
ChildFrameId
Transform
Transforms
の各オブジェクトに 4 つのプロパティがあります。Transforms
の Transform
フィールドを展開して確認できます。
tformFields = tf.Transforms.Transform
メモ: 各オブジェクトが評価され、その Transform
フィールドの値をそれぞれ返すため、コマンドの出力では 53 件の個別の回答が返されます。この形式は常に有効であるとは限らないため、次のコマンドを使用して cell 配列に変換できます。
cellTransforms = {tf.Transforms.Transform}
cellTransforms=1×53 cell array
{1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct} {1x1 struct}
これにより、53 件のオブジェクト エントリがすべて cell 配列に格納され、それらにインデックスを使用してアクセスできるようになります。
また、配列の要素に MATLAB の標準のベクトルと同じ方法でアクセスできます。
tf.Transforms(5)
ans = struct with fields:
MessageType: 'geometry_msgs/TransformStamped'
Header: [1x1 struct]
ChildFrameId: '/imu_link'
Transform: [1x1 struct]
53 件のリストで 5 番目の変換の並進成分にアクセスします。
tf.Transforms(5).Transform.Translation
ans = struct with fields:
MessageType: 'geometry_msgs/Vector3'
X: 0.0599
Y: 0
Z: -0.0141
ROS ネットワークのシャットダウン
サンプル ノード、パブリッシャーおよびサブスクライバーを ROS ネットワークから削除します。
exampleHelperROSShutDownSampleNetwork
ROS マスターをシャットダウンしてグローバル ノードを削除します。
rosshutdown
Shutting down global node /matlab_global_node_07475 with NodeURI http://dcc521788glnxa64:43543/ and MasterURI http://localhost:54319. Shutting down ROS master on http://172.30.179.123:54319.
次のステップ
イメージ、点群、およびレーザー スキャン メッセージの処理の例については、Work with Specialized ROS Messagesを参照してください。
応用例については、Gazebo およびシミュレートされた TurtleBot の入門または実際の TurtleBot の使用開始の例を参照してください。