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); }