1. 程式人生 > 其它 >ROS與boost:bind()簡單解析

ROS與boost:bind()簡單解析

技術標籤:ROS

1 boost:bind()

bind接收的第一個引數必須是一個可呼叫的物件f包括函式、函式指標、函式物件和成員函式指標,之後bind最多接受9個引數,引數數量必須與f的引數數量相等,這些引數被傳遞給f作為形參。
繫結完成後,bind會返回一個函式物件ob(類似auto ob = boost::bind(f,...)),它內部儲存了f的拷貝,具有operator(),返回值型別被自動推導為f的返回型別。在發生呼叫時這個函式物件ob將把之前儲存的引數轉發給f完成呼叫.
如:

void func(x,y);

那麼,他等價於一個具有無參operator()的bind函式物件呼叫:

auto ob = boost::bind(func,a1,a2)();//ob()==func(a1,a2);
//因為bind()裡沒有佔位符,所以ob()無引數,a1,a2作為引數直接輸入func

一般來說boost::bind有兩種方式的呼叫,一種是對自由方法,也即非類方法, 一種是對類方法.

  • 對自由方法來說,直接boost::bind(函式名, 引數1,引數2,…)
  • 對類方法來說,直接boost::bind(&類名::方法名,類例項指標,引數1,引數2)
1.1 非類方法

bind(f, _1, 5)(x)等同於f(x, 5).這裡的 _1 相當於一個佔位符,用來代替第一個輸入引數。又如:

bind(f, 5, _1)(x);                     // f(5, x)
bind(f, _2, _1)(x, y);                 // f(y, x)
bind(g, _1, 9, _1)(x);                 // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z);          // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z);          // g(x, x, x)

比如:

void func(int a, int b, int c);
boost::bind(func,
7, _1, _2);

boost::bind()會返回一個函式物件,所以boost::bind(func, 7, _1, _2)得到一個函式物件ob,即ob = boost::bind(func, 7, _1, _2).當我們呼叫ob(3,4)時,相當於呼叫func(7,3,4),如果連著一起寫那就是boost::bind(func, 7, _1, _2)(3, 4);

需要注意的一點是,boost::bind()裡的引數個數一定要與被bind包括的函式的形參個數相同,否則這個bind函式物件ob就無法生成並報錯.

1.2 類方法

如:

cb = boost::bind(&NodeExample::configCallback, node_example, _1, _2);

其中的 node_example是指標變數NodeExample *node_example = new NodeExample();
因此boost::bind(&NodeExample::configCallback, node_example, _1, _2)的意思就是 node_example -> configCallback(x, y);

又如:

boost::bind(&MyNode::doneCb, this, _1, _2);

意思就是this -> doneCb(x, y) 這裡的x,y 分別為第一個和第二個輸入引數.

2 ROS與bind()

2.1

當我們訂閱一個訊息時候,會呼叫一個返回函式。如:

ros::Subscriber topic_sub=n.subscribe<std_msgs::Int8>("/topic", 10, Callback);

這樣Callback函式應該包含一個引數,即

void Callback(const std_msgs::Int8::ConstPtr& msg){}

但是,如果我們想要多引數傳入的話,就需要使用boost庫中的bind函式。例如,當我們的回撥函式是這樣的:

void Callback(const std_msgs::Int8::ConstPtr& msg, int& x, int& y){}
2.2 示例
#include <ros/ros.h>
#include <std_msgs/Int8.h>

int index1 = 1;
int index2 = 2;
void Callback(const std_msgs::Int8::ConstPtr &msg, int &x, int &y) {
  printf("%d", *msg);
  printf("%d \r\n", x);
  printf("%d \r\n", y);
}
void Callback(const std_msgs::Int8::ConstPtr &msg) { printf("%d \r\n", *msg); }

int main(int argc, char **argv) {
  ros::init(argc, argv, "multi_callback");
  ros::NodeHandle n;
  ros::NodeHandle private_nh("~");

  int rate;

  private_nh.param("rate", rate, 40);

  // ros::Subscriber scan_sub=n.subscribe<std_msgs::Int8>("/topic", 10, 
        //boost::bind(&Callback, _1, index1, index2));//①
  ros::Subscriber scan_sub = n.subscribe<std_msgs::Int8>("topic", 10, Callback);//②
  ros::Rate r(rate);
  while (n.ok()) {
    ros::spinOnce();
    r.sleep();
  }
  return 0;
}

當使用①函式時

ros::Subscriber scan_sub=n.subscribe<std_msgs::Int8>("/topic", 10, \
        boost::bind(&Callback, _1, index1, index2));//①

返回函式呼叫的是:

void Callback(const std_msgs::Int8::ConstPtr &msg, int &x, int &y) {
  printf("%d", *msg);
  printf("%d \r\n", x);
  printf("%d \r\n", y);
}

當使用②函式時

ros::Subscriber scan_sub = n.subscribe<std_msgs::Int8>("topic", 10, Callback);//②

返回函式呼叫的是:

void Callback(const std_msgs::Int8::ConstPtr &msg) { printf("%d \r\n", *msg); }
3 參考

ROS入門(五) C++使用boost::bind 訂閱訊息中的返回函式傳入多個引數

boost::bind的使用

ROS與boost::bind( )