ROS講座110 ROSでntpをする

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 16.04 |
| ROS | Kinetic |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要
ロボットシステム、特にROSは時刻についてべったり依存していて、Rvizの表示などでは時刻が正しいことが前提です。しかしロボットシステムが複数のPCに分かれていて、かつインターネットにつながっていない状態では時刻がずれることがあります。
前回はchronyを直接使って時刻を合わせましたが、今回はROSのntpd_driverを使って時刻合わせをしてみます。

# 設定 

## インストール
ntpd_driverはntpdとchronyの両方に対応しているようですが今回はchronyを使います。

```shell:インストール
sudo apt-get install chrony
sudo apt install ros-kinetic-ntpd-driver 
```

## 設定ファイルの追加

```text:/etc/chrony/chrony.confに追加
### SHM driver
refclock SHM 0:perm=0666 delay 0.5 refid ROS
```

chronyに対してshared memory経由で時刻合わせのコマンドを送れるようにしています。`perm=0666`は読み書き権限でこれがないと一般ユーザーから命令ができません。

## chronyの再起動

```
sudo systemctl restart chrony
```
もしくはPCの再起動をします。

## 共有メモリの確認
chronyが共有メモリを張っているかを`ipcs`コマンドで確認できます。


```text:ipcsコマンドの結果
------ メッセージキュー --------
キー     msqid      所有者  権限     使用済みバイト数 メッセージ

------ 共有メモリセグメント --------
キー     shmid      所有者  権限     バイト  nattch     状態      
0x00000000 1409024    ubuntu     600        16777216   2          対象       
0x00000000 819201     ubuntu     600        16777216   2                       
0x00000000 688130     ubuntu     600        524288     2          対象       
0x00000000 983043     ubuntu     600        524288     2          対象       
0x4e545030 458756     root       666        96         1                       
0x00000000 1245189    ubuntu     600        524288     2          対象       
0x00000000 1114118    ubuntu     600        524288     2          対象       
0x00000000 1343495    ubuntu     600        524288     2          対象       
0x00000000 1507336    ubuntu     600        524288     2          対象       
0x00000000 1867786    ubuntu     600        524288     2          対象       
0x00000000 1736715    ubuntu     600        524288     2          対象       
0x00000000 1900556    ubuntu     600        393216     2          対象       
0x00000000 1998861    ubuntu     600        393216     2          対象       
0x00000000 2031630    ubuntu     600        524288     2          対象       
0x00000000 2261007    ubuntu     600        524288     2          対象       

------ セマフォ配列 --------
キー     semid      所有者  権限     nsems   
```

`0x4e545030 458756 root 666 96 1`がchronyの共有メモリを表しています。

# 使い方

## 一度時刻を過去にセットする。
ntpd_driverの仕様で、時刻が一定（2009/02/14 08:31:30）よりも過去でないと時刻を書き換えないようになっています。
ubuntuのguiで時刻を書き換えるかdateコマンドを使います。

```shell:時刻変更
sudo date -s "01/1 13:00 2000"
```

## ntpd_driverノードの起動

```shell:1つ目のターミナル
roscore
```

```shell:2つ目のターミナル
rosrun ntpd_driver shm_driver _shm_unit:=0 _fixup_date:=true
```

## 時刻の変更

```shell:時刻変更のrostopicの送信
rostopic pub -1 /ntpd_shm/time_ref sensor_msgs/TimeReference "header:
  seq: 0
  stamp:
    secs: 0
    nsecs: 0
  frame_id: ''
time_ref:
  secs: 600000000
  nsecs: 0
source: ''" 
```

このように time_refのフィールドに設定したい時刻を投げます。するとntpd_driverを起動している画面で以下のように出て時刻が変更されます。

```text:時刻変更をしたログ
[ INFO] [946760738.650489385]: Setting system date to: 600000000.000000
[ INFO] [600000000.002175932]: The system date is set.
```

# コメント
今回の例だけではただ時刻設定をROSからできるだけですが、例えばntpd_driverをロボットで起動して、操作側のノートPCから/time_refのコマンドを送ればノートPCの時刻にロボットの時刻を合わせられます。
またGPSモジュールが接続されている場合はGPSの時刻に合わせるという使い方もできます。

# 参考
[ntpd_driver](https://github.com/vooon/ntpd_driver)

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)