问题描述
我正在尝试编写一个类来处理基于 ROS 的机器人(特别是使用 Arduino IDE 的 ESP32 芯片)的电机控制。
为此,我想实现一个 ROS 串行订阅者,它在收到新消息时调用回调函数。回调函数将消息数据存储在类的实例变量中,因此我可以轻松地将其与类的其他函数一起使用。
这使得回调函数成为非静态的,因此我使用 std::bind
将它绑定到我的类的特定实例,同时为消息保留一个占位符。
#include <ros.h>
#include <geometry_msgs/Twist.h>
ros::NodeHandle nh;
const char cmd_vel_topic[] = "/cmd_vel"
class MotorControlInterface {
public:
// FreeRTOS task to call from main
void TaskMotorControl(void *pvParameters)
{
ros::Subscriber<geometry_msgs::Twist> twist_sub
(
// The topic to subscribe to
cmd_vel_topic,// Reference to callback function that is bound to this instance of the class
&std::bind(&MotorControlInterface::twistCallback,this,std::placeholders::_1),);
nh.subscribe(twist_sub);
for(;;)
{
// Do some stuff with veLocity commands
handleMotorSpeeds();
vTaskDelay( 10 );
}
};
private:
// Instance variable I want to store message data in
double vel_cmd_x;
// Callback function
void twistCallback(const geometry_msgs::Twist& twist_msg)
{
// Save veLocity command
vel_cmd_x = twist_msg.linear.x;
};
};
我收到的错误信息:
Arduino: 1.8.15 (Linux),Board: "ESP32 Dev Module,disabled,Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS),240MHz (WiFi/BT),QIO,80MHz,4MB (32Mb),921600,None"
/home/ubuntu/Arduino/***/*****.ino: In member function 'void MotorControlInterface::TaskMotorControl(void*)':
*****:83:87: error: taking address of temporary [-fpermissive]
&std::bind( &MotorControlInterface::twistCallback,std::placeholders::_1)
^
*****:84:7: error: no matching function for call to 'ros::Subscriber<geometry_msgs::Twist>::Subscriber(const char [9],std::_Bind_helper<false,void (MotorControlInterface::*)(const geometry_msgs::Twist&),MotorControlInterface*,const std::_Placeholder<1>&>::type*)'
);
^
In file included from /home/ubuntu/Arduino/libraries/ros_lib/ros/node_handle.h:60:0,from /home/ubuntu/Arduino/libraries/ros_lib/ros.h:38,from /home/ubuntu/Arduino/*****/*****.ino:28:
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:107:3: note: candidate: ros::Subscriber<MsgT,void>::Subscriber(const char*,ros::Subscriber<MsgT,void>::CallbackT,int) [with MsgT = geometry_msgs::Twist; ros::Subscriber<MsgT,void>::CallbackT = void (*)(const geometry_msgs::Twist&)]
Subscriber(const char * topic_name,CallbackT cb,int endpoint = rosserial_msgs::TopicInfo::ID_SUBSCRIBER) :
^
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:107:3: note: no kNown conversion for argument 2 from 'std::_Bind_helper<false,const std::_Placeholder<1>&>::type* {aka std::_Bind<std::_Mem_fn<void (MotorControlInterface::*)(const geometry_msgs::Twist&)>(MotorControlInterface*,std::_Placeholder<1>)>*}' to 'ros::Subscriber<geometry_msgs::Twist>::CallbackT {aka void (*)(const geometry_msgs::Twist&)}'
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate: constexpr ros::Subscriber<geometry_msgs::Twist>::Subscriber(const ros::Subscriber<geometry_msgs::Twist>&)
class Subscriber<MsgT,void>: public Subscriber_
^
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate expects 1 argument,2 provided
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate: constexpr ros::Subscriber<geometry_msgs::Twist>::Subscriber(ros::Subscriber<geometry_msgs::Twist>&&)
/home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate expects 1 argument,2 provided
exit status 1
taking address of temporary [-fpermissive]
在我看来,回调函数的 std::bind
没有返回我期望的内容,因此引用失败。不过,根据 this 的说法,返回值是一个函数对象。
由于这是我一段时间以来的第一个 C/C++ 项目,我非常感谢您提供有关如何使其工作的任何建议。我在这上面花了好几个小时,但我不确定如何继续,因为错误消息并没有真正帮助我。
解决方案: This solution 有效:
#include <ros.h>
#include <geometry_msgs/Twist.h>
ros::NodeHandle nh;
const char cmd_vel_topic[] = "/cmd_vel"
class MotorControlInterface {
public:
MotorControlInterface()
: twistSubscriber(cmd_vel_topic,&MotorControlInterface::twistCallback,this)
{
; // Stuff to do in the constructor
};
// FreeRTOS task to call from main
void TaskMotorControl(void *pvParameters)
{
nh.subscribe(twist_sub);
for(;;)
{
// Do some stuff with veLocity commands
handleMotorSpeeds();
vTaskDelay( 10 );
}
};
private:
// Instance variable I want to store message data in
double vel_cmd_x;
ros::Subscriber<geometry_msgs::Twist,MotorControlInterface> twistSubscriber;
// Callback function
void twistCallback(const geometry_msgs::Twist& twist_msg)
{
// Save veLocity command
vel_cmd_x = twist_msg.linear.x;
};
};
解决方法
-
对于 ROS,无需将
std::bind
与ros::Subscriber
构造函数结合使用:对于非静态成员函数ros::NodeHandle::subscribe
实际上有一个相应的重载(其中nh
是您的节点句柄)ros::Subscriber<geometry_msgs::Twist> twist_sub = nh.subscribe(cmd_vel_topic,1,&MotorControlInterface::twistCallback,this);
-
ros::Subscriber<geometry_msgs::Twist> twist_sub {cmd_vel_topic,this}; nh.subscribe(twist_sub);
此外 - 与 ROS 不同 -
boost::function
没有过载,这意味着您根本无法使用boost::bind
或std::bind
的语法。>