# 座標の管理
---
ロボットは多くのパーツで構成されています。多くの場合、パーツは移動できます。そのため、多くの座標系を追跡する必要があります。
---
## TF2
- 座標系(フレームとも呼ぶ)を管理・処理するツール
- ツリー構造の座標系間の接続を維持する
- ユーザーは、位置を表すポイントやベクトルをある座標系から別の座標系に変換できる
- (内部的にトピック`/tf`および`/tf_static`の出版/購読モデルを使って実装されている)
https://wiki.ros.org/tf2
(tfライブラリも存在していますが、tf2のほうが新しいです。)
---
### TFツリー
- 全ての座標系(フレーム)がツリーに繋がっています。
- 位置データは、同じツリー内にある任意の2つのフレーム間で変換可能です。
ツリーの例:
---
### TFツール
*ターミナル*
現在の変換ツリーに関する情報をプリント
```bash
rosrun tf tf_monitor
```
2つの座標系間の変換情報をプリント
```bash
rosrun tf tf_echo <座標系1> <座標系2>
```
*可視化*
TFツリー:`rqt`を実行してから、メニューから Plugins → Visualization → TF Treeを選択
#### turtlesimで試してみよう
以下のコマンドを使って2つの亀ロボットのturtlesimを起動しましょう。
```bash
roslaunch turtle_tf2 turtle_tf2_demo.launch
```
```bash
rosrun turtlesim turtle_teleop_key
```
その後、tfのコマンドを使ってみてください。
```bash
rosrun tf tf_echo turtle1 turtle2
```
rqtを使って、TFツリーを表示してみてください。
---
### TFとRViz
- Addボタンを使って、「TF」の表示を選択
**注意**:RVizがメインな座標系として使っているフレーム(Global OptionsのFixed Frame ⇒ 上の図で赤い矢印がついているところ)を必ず実際にTFツリーに入っているフレームに設定する必要があります。
---
### TF APIの使用
まず、TF用のバッファーと購読者を作成します。
```python
tfBuffer = tf2_ros.Buffer()
listener = tf2_ros.TransformListener(tfBuffer)
```
(購読者を1つだけ使ってください。使用するたびに新しい購読者を作成しないように注意してください。)
変換を取得するには
```python
trans = tfBuffer.lookup_transform(目的のフレーム, 本来のフレーム, rospy.Time(0))
```
(rospy.Time(0)の場合、最新の変換が得られる)
---
Pythonコードの例(`base`フレームから`odom`フレームへの変換)
```python
#!/usr/bin/env python
import rospy
import math
import tf2_ros
import geometry_msgs.msg
import turtlesim.srv
if __name__ == '__main__':
rospy.init_node('tf2_listener')
tfBuffer = tf2_ros.Buffer()
listener = tf2_ros.TransformListener(tfBuffer)
rate = rospy.Rate(10.0)
while not rospy.is_shutdown():
try:
trans = tfBuffer.lookup_transform("odom", "base", rospy.Time())
except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException):
rate.sleep()
continue
rate.sleep()
```
https://wiki.ros.org/tf2/Tutorials/Writing%20a%20tf2%20listener%20%28Python%29
tf2_geometry_msgsパッケージの関数を使えば、lookupTransformで上記のように得られた変換パラメータを使用して、点、ポーズなどの座標変換が行えます。
点の座標変換の例:
```python
import tf2_geometry_msgs
from geometry_msgs.msg import PointStamped, Point
#変換したい点
pt = Point(1,2,0)
#(do_transform_pointはPointStampedを使うので一旦PointをPointStampedに変換します)
pt2 = tf2_geometry_msgs.do_transform_point(PointStamped(point=pt), trans).point
rospy.loginfo(pt)
rospy.loginfo(pt2)
```
---
- 自分のプログラム内でTF変換を公開する(任意) → 以下のチュートリアルを参照
[tf2静的ブロードキャストの作成](https://wiki.ros.org/tf2/Tutorials/Writing%20a%20tf2%20static%20broadcaster%20%28C%2B%2B%29)
[tf2ブロードキャストの作成](
https://wiki.ros.org/tf2/Tutorials/Writing%20a%20tf2%20broadcaster%20%28C%2B%2B%29)
---
### GazeboとTF
Gazeboでシミュレートされているロボットのフレームをブロードキャスト → `robot_state_publisher`ツールを使います
- `rosrun robot_state_publisher robot_state_publisher`、またはlaunchファイルに追加する
---
→ [課題](v2_task.html)
← [実習その1](v2_1.html)
↑ [ホームページ](index.html)