ROS講座06 ROS Logger

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

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 20.04 |
| ROS | Noetic |

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

# 概要
printfデバッグはお手軽で有用な方法です。ROSでもprintfを使うことができますが、多数のROSノードが実行される状況では多数のノードのprintfが混ざってしまうために少々使いにくなります。
その代わりにROSではROS loggerという仕組みが用意されています。ターミナルで表示できるだけでなく、rqt_consoleというLogger情報を統合的に表示するツールもあります。このようなツールがあるためにROSではこのLoggerの仕組みを使い、通常のprintfは使いません。

# ROS loggerをpublishするソースコード

## ソースコード
loggerもprintfと使い方はほぼ変わらずROS_****("文字列", 引数, ...)という形になります。

```c++:basic_lecture/src/basic_logger.cpp
#include <string.h>
#include <ros/ros.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "basic_logger");
  ros::NodeHandle n;
  ros::Rate loop_rate(1);
  // if (ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug))
  // {
  //   ros::console::notifyLoggerLevelsChanged();
  // }

  int count = 0;
  while (ros::ok())
  {
    ROS_DEBUG("log:%i", count);
    ROS_INFO("log:%i", count);
    ROS_WARN("log:%i", count);
    ROS_ERROR("log:%i", count);
    ROS_FATAL("log:%i", count);

    ros::spinOnce();
    loop_rate.sleep();
  }
  return 0;
}
```

##launchファイル
```xml:basic_lecture/launch/logger.launch
<launch>
  <node name="logger1" pkg="basic_lecture" type="basic_logger" />
  <node name="logger2" pkg="basic_lecture" type="basic_logger" />
</launch>
```

## CmakeListの設定

```cmake:basic_lecture/CMakeLists.txtへの追加
add_executable(basic_logger src/basic_logger.cpp)

target_link_libraries(basic_logger
  ${catkin_LIBRARIES}
)
```

# ビルド
```shell
cd ~catkin_ws
catkin build
```

# 実行
各ターミナルごとに実行前に`source ~/catkin_ws/devel/setup.bash`を実行する必要があります。

## ノード単体での実行
```shell:1つ目のターミナル
roscore
```

```shell:2つ目のターミナル
rosrun basic_lecture basic_logger 
```
### 表示例
以下のように表示されます。
![basic_logger1.png](https://qiita-image-store.s3.amazonaws.com/0/254442/2b4f98b1-b37c-ca99-989b-41dd96d6093e.png)

### Debugの表示方法
初期設定では`DEBUG`レベルのメッセージは表示されません。これを表示するようにするには以下をターミナルに打ち込むか、

```shell
rosservice call /basic_logger/set_logger_level {"logger: 'ros', level: 'debug'"}
```

もしくはソースコード中に以下のように追記します（上のソースコードでコメントアウトされている部分でです）。

```C++
if( ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug) ) {
   ros::console::notifyLoggerLevelsChanged();
}
```

## launch時でのROS logger

```shell:実行
roslaunch basic_lecture logger.launch
```

##表示
![basic_logger2.png](https://qiita-image-store.s3.amazonaws.com/0/254442/c84b5332-38cd-330e-67a1-9cec11722a3d.png)

この場合はError、Fatalのレベルしか表示されません。INFO、WARNINGのレベルも表示させたいい場合は<node>タグの属性で`output="screen"`とします

# rqt_console
上記のlaunchを動かしたまま以下のコマンドを実行します。

```shell
rosrun rqt_console rqt_console
```

![rqt_console.png](https://qiita-image-store.s3.amazonaws.com/0/254442/f3f43d06-6c32-62ec-8217-33e7e7b4fc2c.png)

このようなGUI画面が表示されます。真ん中の「Exlude Messages」で表示するloggerを選択できます。

# コメント
大規模でエラーの管理が難しくなるとprintfよりかは便利に使えるツールです。基本的に使うのはInfoとErrorの2つです。ノードを単体で動かしている時に見たいログをInfoで書き、機能に影響が起きるような状況が起きたらErrorでログを出力します。
5つのレベルがありますが、あまり厳格には使用方法は決まっていません。

# 参考
[ROS wiki](http://wiki.ros.org/roscpp/Overview/Logging)

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