rosparamの使い方メモ

## 概要

* rosparamの使い方についてのメモ
* コマンドラインから使用
* launchファイルから使用
* C++, Pythonから使用

## 環境

* ubuntu 16.04
* ROS kinetic

## rosparamとは

* wiki
    * http://wiki.ros.org/rosparam
* roscore起動時に一緒に起動されるROS Parameter Server
* 定数などのパラメータを設定するために使用する
* 各値はROS Parameter Serverに登録される
    * /foo/bar とパスを指定することで各パラメータにアクセスできる
* roscore終了時に登録した値は全て削除される
* 設定できる値は
    * int
    * double
    * string
    * date
    * list
    * base64

### コマンドラインでの使い方

#### 設定されてる値のパス一覧を取得

```bash
$ rosparam list
```

#### 値を設定

```bash
$ rosparam set /foo hogehoge
```

#### 値を取得

```bash
$ rosparam get /foo
```

* 階層構造になってるので子の要素がある場合は連想配列として取得できる

#### 値を削除

```bash
$ rosparam delete /foo
```

* getと同じくこの要素がある場合は指定したパス以下の値を全て削除する

#### 設定値をyamlファイルに書き出す

```bash
$ rosparam dump config.yaml
```

#### yamlから設定値をロードする

```bash
$ rosparam load config.yml
```

### launchファイルから使用

* launchファイルでrosparamタグを使用するとroslaunch時に読み込みや削除ができる

```xml
<launch>
  <rosparam command="load" file="$(find package_name)/example.yaml" />
  <rosparam command="delete" param="my/param" />
</launch>
```

* nodeなどと同じくネームスペースも指定できる

```xml
<launch>
  <rosparam ns="foo" command="load" file="$(find package_name)/example.yaml" />
</launch>
```

### Pythonから扱う

* rosparamモジュールを使う方法と、rospyを使う方法があります

#### rosparam

rosparamコマンドのラッパー的な感じで、
get,setはもちろんできますが、コマンドでできるloadとかdumpをしたい場合はこちらを使います。

```py
>>> import rosparam
>>> rosparam.get_param("/foo/bar")
1
>>> rosparam.set_param("/foo/bar/path", "value")
>>> rosparam.get_param("/foo/bar/path")
'value'
>>> rosparam.get_param("/foo")  # 階層になっている場合はdictで取得できる
{'bar': {'path': 'value'}}
```

#### rospy

rospyでもget, setはできますが、loadやdumpはできません。
rosparamと同じく存在しないキーを参照しようとするとExceptionが発生しますが、
存在しない場合のデフォルト値をしていすることができます。

```py
>>> import rospy
>>> rospy.get_param("/foo/bar/")
{'path': 'value'}
>>> rospy.get_param("/foo/bar/path")
'value'
>>> rospy.get_param("/foo/bar/undefined")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/client.py", line 465, in get_param
    return _param_server[param_name] #MasterProxy does all the magic for us
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/msproxy.py", line 123, in __getitem__
    raise KeyError(key)
KeyError: '/foo/bar/undefined'
>>> print rospy.get_param("/foo/bar/undefined", None)
None
```

### C++から扱う

C++の場合はNodeHandleからrosparamを扱うことができます。

```cpp
#include <ros/ros.h>

int main(int argc, char** argv) {
  ros::init(argc, argv, "rosparam");
  ros::NodeHandle nh;

  // 取得したいパラメータの値に対応する型の変数を引数で渡す
  int int_param;
  nh.getParam("/foo/bar", int_param);

  std::cout << int_param << std::endl;
  return 0;
}
```

* 実行結果

```bash
$ rosrun rosparam_ex rosparam_ex_node 
1
```

複数の値を一度に取得したい場合はXmlRpcValueを使います。

```cpp
#include <ros/ros.h>

int main(int argc, char** argv) {
  ros::init(argc, argv, "rosparam");
  ros::NodeHandle nh;

  XmlRpc::XmlRpcValue params;
  nh.getParam("/foo/bar", params);

  std::cout << params << std::endl;

  std::cout << params["path"] << std::endl;  // std::mapと同じ要領で値を取得できる

  return 0;
}
```

* 実行結果

```bash
$ rosrun rosparam_ex rosparam_ex_node 
[path:value]
value
```


rosparamを使用することで初期化の設定などを変えることができるので、
起動時の引数が多くなってしまった時などはユースケースごとにyamlを作成しておくと便利です。