【发布时间】:2021-07-27 19:23:37
【问题描述】:
我正在尝试编写一个类来处理基于 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, this, 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, void (MotorControlInterface::*)(const geometry_msgs::Twist&), MotorControlInterface*, 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;
};
};
【问题讨论】:
-
返回错误与其说是错误,不如说是生命周期。如果您不将对象存储在某个地方,该对象几乎会立即超出范围,一旦超出范围,指向它的指针就没有用了。
-
我尝试将
std::bind的返回值存储到这样的类变量中:std::function<void(geometry_msgs::Twist)> selfTwistCB = std::bind( &MotorControlInterface::twistCallback, this, std::placeholders::_1 );。当我使用对此类变量的引用时,我会遇到以下错误:pastebin。显然我没有为变量选择正确的数据类型? -
我有同样的问题,你的解决方案在 Arduino 上对我不起作用,因为编译器不理解语法
ros::Subscriber<geometry_msgs::Twist, MotorControlInterface> twistSubscriber;- 错误:类模板“ros::Subscriber”的参数太多。你是怎么做到的?
标签: c++ arduino callback ros non-static