ROS2でのparameter変更に対するcallback関数の設定

[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)

ROS2でparameterを変更したときに呼ばれるcallback関数の使い方について．

# 概要
callback関数を設定する関数は以下のとおり

- rclcpp::Node::set_on_parameters_set_callback

現在(2019/7/4)，[公式のAPI]では以下の関数を使用するようになっているが，これは[Roadmap]によると廃止予定らしい

-rclcpp::Node::register_param_change_callback

# 使用方法
## set_on_parameters_set_callback
[Roadmap]によると以下のように定義されている．

```c++
using OnParametersSetCallbackType =
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;

OnParametersSetCallbackType
rclcpp::Node::set_on_parameters_set_callback(
  OnParametersSetCallbackType callback);
```

ただ，[公式のgithubのrclcpp](https://github.com/ros2/rclcpp/blob/master/rclcpp/include/rclcpp/node_interfaces/node_parameters_interface.hpp)では以下のように定義されている．

```c++
using OnParametersSetCallbackType =
    std::function<
    rcl_interfaces::msg::SetParametersResult(const std::vector<rclcpp::Parameter> &)
    >;

OnParametersSetCallbackType
rclcpp::Node::set_on_parameters_set_callback(
  OnParametersSetCallbackType callback);
```

どちらが正しいのか分からないので，とりあえず後者を正しいものと考えておく．
どちらにしても，例えば作成するcallback関数の名前をparam_reset_callbackとでもすると，以下のように使用する．

```c++:ROS風
auto res = node->set_on_parameters_set_callback(
  std::bind(param_reset_callback, std::placeholders::_1);
);
```

クラス化したノード内では以下のように使用する．例としてクラスの名前をMyClassとする．

```c++:クラス化したノード内
auto res = this->set_on_parameters_set_callback(
  std::bind(&MyClass::param_reset_callback, this, std::placeholders::_1);
);
```

## 設定するcallback関数
パラメータが変更された時に呼ばれるcallback関数(ここでは前に述べた例に則ってparam_reset_callbackの名前を使用)について述べる．
前に述べた定義から，callback関数はOnParametersSetCallbackTypeで定義されたstd::functionの形となる．つまり，

- 返り値
    - rcl_interfaces::msg::SetParametersResult
- 引数:
    - const std::vector<rclcpp::Parameter> & params

返り値となるrcl_interfaces::msg::SetParametersResultは[公式githubの当該ページ](https://github.com/ros2/rcl_interfaces/blob/master/rcl_interfaces/msg/SetParametersResult.msg)によると以下の値を設定できるメッセージとなっている．

- bool successful
- string reason
    - successful=falseの時の理由なのでtrueの時には""でいいんじゃないかな

### callback関数の宣言

```C++
rcl_interfaces::msg::SetParametersResult param_reset_callback(const std::vector<rclcpp::Parameter> & params);
```

### callback関数の実装と使用
例えばパラメータ"parapara"を持つ場合の例．
ノードをクラス化した例だがROS風でも同様．

```C++
// callback関数の実装
rcl_interfaces::msg::SetParametersResult
MyClass::param_reset_callback(const std::vector<rclcpp::Parameter> & params){
  auto result = std::make_shared<rcl_interfaces::msg::SetParametersResult>();
  for(auto&& param : params){
    if(param.get_name() == "parapara"){
      // なんかの処理
    }else if(... // 他のパラメータも同様に

    }else{
      // 全パラメータに対して条件分岐するなら，ここは対象外のパラメータ．つまりなにか変なことになっている．
      result->successful = false;
      result->reason = "wrong param"
      return *results;
    }
  }
  // 全パラメータに対して処理が終わったのでOKを返す
  result->successful = true;
  result->reason = "";
  return *result;
}

MyClass::MyClass(.... // MyClassのコンストラクタにて

{
...
  auto res = this->set_on_parameters_set_callback(
    std::bind(&MyClass::param_reset_callback, this, std::placeholders::_1);
  );
}
```


[公式のAPI]:http://docs.ros2.org/dashing/api/rclcpp/classrclcpp_1_1Node.html#aed9fcbbe42dbe03008ae4bfcfa0452f0
[Roadmap]:https://index.ros.org/doc/ros2/Releases/Release-Dashing-Diademata/