LoginSignup
6
4

More than 5 years have passed since last update.

オンデマンドサブスクライブによるデータ通信量節約

Last updated at Posted at 2014-02-13

ROSではpub/sub型のメッセージ通信を行うことで異なるノード間のデータ受け渡しを実現している。

基本的には以下の手順でデータが授受される。

  1. 送信側が送信可能であることをbroadcastする(pub->advertise)
  2. 受信側が送信側のデータを購読(sub->subscribe)
  3. 送信側がデータを送信(pub->publish)
  4. 受信側がデータを受信しコールバック関数が呼ばれる

基本的には何かのデータを使いたくなったらサブスクライブして、データが来たらコールバックで処理するという形でよい。

しかしながら、以下のような場合

img1.png

重い処理をオンデマンドにする、すなわち処理結果を使うノードがsubscribeしたときだけカメラ画像をサブスクライブし、自身がpublishするようにすれば、カメラ画像の取得と重い画像処理をする回数を必要最小限にすることができる。

このためには画像の重い画像処理ノードを以下のように書けばいい。

class ImageProc {
  ros::NodeHandler _n;
  ros::Publisher   _pub;
  ros::Subscriber  _sub;
public:
  ImageProc(){
    _n.advertise("image_proc_result",10);
  void callback(typeof(msg) msg){
    // 重い処理 例:SIFT特徴点抽出
    _pub.publish(result);
  }

  void checkSubscribers(){
    if(_pub.getNumSubscribers() == 0) {
      if(_sub) { // 誰も自身をサブスクライブしなかったら自身もサブスクライブを止めてコールバックが呼ばれないようにする
        _sub.shutdown();
        ROS_INFO("unsubscribe");
      }
    } else {
      if (!_sub){
        _sub = _n.subscribe("camera_image", 1, &ImageProc::callback, this);
        ROS_INFO("subscribe");
      }
    }
  }

int main(int argc, char *argv[]){
  ros::init (argc, argv, "image_proc");
  ImageProc imgproc;
  ros::Rate r(10);

  while(ros::ok()){
    ros::spinOnce();
    imgproc.checkSubscribers(); // ポーリング毎に自身のサブスクライバを確認
    r.sleep();
  }

  return 0;
}

まあ、当たり前ですね。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4