# 独自のメッセージファイルの作り方

## ROSチュートリアルの流れ

1. [ROSパッケージの作り方](/project/ros_tutorial/how_to_create_pkg.md)
2. [トピックの書き方](/project/ros_tutorial/how_to_write_topic.md)
3. [独自のメッセージファイルの作り方](/project/ros_tutorial/how_to_create_msg.md) ←今ここ
4. [まとめて起動するやり方](/project/ros_tutorial/how_to_use_launch.md)
5. [サービスの書き方](/project/ros_tutorial/how_to_write_service.md)
6. [独自のサービスファイルの作り方](/project/ros_tutorial/how_to_create_srv.md)

## はじめに

この章では、独自のメッセージファイルを作成し、ROSで使用する方法を解説します。

独自のメッセージファイルをROSで使用するためには、 `CMakeLists.txt`と`package.xml`というファイルを編集します。

この2つのファイルは、ROSチュートリアルの[ROSパッケージの作り方](/project/ros_tutorial/how_to_create_pkg.md)でパッケージを作成したときに自動で出来たファイルです。 `package.xml`はパッケージの設定が書いてあり、`CMakeLists.txt`はビルドする際の設定が書いてあります。

[トピックの書き方](/project/ros_tutorial/how_to_write_topic.md)ではUNIX時間を配信しましたが、この章では現在日時を送るものに改良したいと思います。

まず、現在日時を送るためのメッセージファイルから作成します。

## メッセージファイルの作り方

メッセージファイルは`msg`ディレクトリに置きます。 無い場合は`msg`ディレクトリを作りましょう。

```
roscd ros_tutorial/
mkdir msg
```

日付と時間を送るためのメッセージを`Date.msg`とします。

```
vim msg/Date.msg
```

`Date.msg`の中は以下のように書きます。

```
int32 date
float64 time
```

1行目はint型32ビットの`date`で、2行目はFloat型の`time`という名前にしています。

#### ここからが**重要**です。

#### まず`package.xml`を編集します。

```
roscd ros_tutorial/
vim package.xml
```

40行目の`<build_depend>message_generation</build_depend>`と、46行目の`<exec_depend>message_runtime</exec_depend>`のコメントアウトを外します。

![](/files/-LYRPWmSS7i1apisAbE1)

#### 次に`CMakeLists.txt`を編集します。

```
vim CMakeLists.txt
```

10行目の`find_package`に、14行目ように`message_generation`を追加します。

![](/files/-LYRPWmUja7IuWACbKOC)

51行目の`add_message_files`のコメントアウトを外し、53行目に`Date.msg`を追加する。

![](/files/-LYRPWmWARLDNQQg3BQB)

71行目から74行目の`generate_massages`のコメントアウトを外します。

![](/files/-LYRPWmYViEVTNOTySq-)

108行目の`catkin_package`の`CATKIN_DEPENDS`のコメントアウトを外し、`message_runtime`を追加します。

![](/files/-LYRPWm_fheMSNzMfvcx)

`catkin_ws`に移動し`catkin_make`を行います。

```
cd ~/catkin_ws
catkin_make
```

これで、ビルドが通れば正常に`Date.msg`が作成されたはずです。

確認してみましょう。 以下のように打ち込み、

```
rosmsg show ros_tutorial/Date
```

以下のように表示されたら完了です。

```
int32 date
float64 time
```

## プログラムを改良

先程作成したメッセージファイルを使用して、プログラムを改良しましょう。 まず`ros_tutorial`に移動します。

```
roscd ros_tutorial
```

### パブリッシャ

`time_pub2.py`という名前にします。

```
vim scripts/time_pub2.py
```

{% code title="time\_pub2.py" %}

```python
#!/usr/bin/env python                                                           
import rospy
from ros_tutorial.msg import Date    
from datetime import datetime

def talker():
    l = []
    d = Date()
    rate = rospy.Rate(10)
    while not rospy.is_shutdown():
        d.date = ''
        d.time = ''

        now = datetime.now()
        l = str(now)

        for i in range(0,10):
            d.date += l[i]
        for i in range(11,25):
            d.time += l[i]
        d.date = int(d.date.replace('-', ''))
        d.time = float(d.time.replace(':',''))
        pub.publish(d)
        rate.sleep()

if __name__ == '__main__':
    rospy.init_node('time_pub')
    pub = rospy.Publisher('Date_and_Time', Date , queue_size=1)
    talker()
    rospy.spin()
```

{% endcode %}

実行権限を与えます。

```
chmod +x scripts/time_pub2.py
```

### コード解説

```
#!/usr/bin/env python                                                           
import rospy
from ros_tutorial.msg import Date
from datetime import datetime
```

新たに、先程作成した`Date`をインポートしています。また現在日時を取得するために必要なモジュール`datetime`もインポートしています。

```
def talker():
```

`talker`という名前の関数を定義しています。

```
    l = []
    d = Date()
```

`l = []`はリストの初期化を行っています。

`d = Date()`はメッセージの`Date`を`d`という名前でインスタンス化しています。

```
    rate = rospy.Rate(10)
    while not rospy.is_shutdown():
```

シャットドウンされるまで10Hzでwhile内のコードを実行します。

```
        d.date = ''
        d.time = ''
```

`Date.msg`の`date`と`time`を初期化しています。

```
        now = datetime.now()
        l = str(now)
```

現在日時を取得し、配列にして`l`に渡しています。

```
        for i in range(0,10):
            d.date += l[i]
        for i in range(11,25):
            d.time += l[i]
```

for文で配列の0\~10番目を日付として`date`に渡しています。同様に配列の11\~25番目を時間として`time`に渡しています。

しかし、このままだと`-`や`:`の文字が含まれているため、

```
        d.date = int(d.date.replace('-', ''))
        d.time = float(d.time.replace(':',''))
        pub.publish(d)
        rate.sleep()
```

`replace`を用いて`-`や`:`の文字を取り除き、`int`型と`float`型にしてパブリッシュしています。

### サブスクライバ

サブスクライバはほとんど変わらないため、`time_sub.py`をコピーし、`time_sub2.py`という名前で保存しましょう。

```
cp scripts/time_sub.py scripts/time_sub2.py
vim scripts/time_sub2.py
```

3行目と6行目、10行目に変更を加えます。

{% code title="time\_sub2.py" %}

```python

#!/usr/bin/env python
import rospy
from ros_tutorial.msg import Date  #changed

def callback(message):
    print("date : %d , time : %f" % (message.date,message.time) )  #changed

if __name__ == "__main__":
    rospy.init_node('time_sub')
    sub = rospy.Subscriber('Date_and_Time', Date , callback)  #changed
    rospy.spin()
```

{% endcode %}

```
chmod +x scripts/time_sub2.py
```

### コード解説

変更点だけ解説していきます。

```
from ros_tutorial.msg import Date
```

`Date`をインポートしています。

```
    print("date : %d , time : %f" % (message.date,message.time) )
```

`date`はint型のため`%d`、`time`はfloat型のため`%f`で表示しています。

```
    sub = rospy.Subscriber('Date_and_Time', Date , callback)
```

トピック名をメッセージの型を`Date`に変更しています。

## 実行方法

それぞれ別のターミナルで実行しましょう。

```
roscore
```

```
rosrun ros_tutorial time_pub2.py
```

```
rosrun ros_tutorial time_sub2.py
```

## 実行結果

```
$ rosrun ros_tutorial time_sub2.py 
date : 20181108 , time : 224947.85194
date : 20181108 , time : 224947.95175
date : 20181108 , time : 224948.05449
date : 20181108 , time : 224948.15677
date : 20181108 , time : 224948.25193
date : 20181108 , time : 224948.35248
date : 20181108 , time : 224948.45211
date : 20181108 , time : 224948.55515
date : 20181108 , time : 224948.6551
date : 20181108 , time : 224948.75641
date : 20181108 , time : 224948.85298
date : 20181108 , time : 224948.9519
date : 20181108 , time : 224949.05382
date : 20181108 , time : 224949.15634
date : 20181108 , time : 224949.25606
date : 20181108 , time : 224949.35245
date : 20181108 , time : 224949.45277
date : 20181108 , time : 224949.55351
date : 20181108 , time : 224949.65224
date : 20181108 , time : 224949.75421
date : 20181108 , time : 224949.8536
date : 20181108 , time : 224949.95257
```

2018年11月08日の22時49分49.95257秒を指しています。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://raspimouse-sim-tutorial.gitbook.io/project/ros_tutorial/how_to_create_msg.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
