
To correctly create a subscription in ROS 2 and bind it to a member function, you need to use std::bind
to properly link the member function with the class instance. The line you've commented out should be used. Here is the corrected version of your code snippet:要在 ROS 2 中正确创建订阅并将其绑定到成员函数,需要使用 std::bind
将成员函数与类实例正确连接起来。应该使用你注释掉的那一行。以下是您的代码片段的更正版本:
cpp#include <functional>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "geometry_msgs/msg/twist.hpp"
class GravityDirFinder : public rclcpp::Node
{
public:
GravityDirFinder()
: Node("gravity_dir_finder")
{
map_name_subscriber_ = this->create_subscription<std_msgs::msg::String>(
"current_map_file", 1,
std::bind(&GravityDirFinder::triggerFinder, this, std::placeholders::_1),
options);
}
private:
void triggerFinder(const std_msgs::msg::String::SharedPtr msg)
{
// keep the robot stationary when collecting IMU data
geometry_msgs::msg::Twist zero_twist;
zero_twist.linear.x = 0.0;
zero_twist.linear.y = 0.0;
zero_twist.linear.z = 0.0;
zero_twist.angular.x = 0.0;
zero_twist.angular.y = 0.0;
zero_twist.angular.z = 0.0;
// Additional code to handle the IMU data
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr map_name_subscriber_;
rclcpp::SubscriptionOptions options; // Initialize options if needed
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<GravityDirFinder>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
Key Points:要点
- Binding the Member Function: The commented-out line using
std::bind
is necessary to bind the member functiontriggerFinder
to the subscription callback correctly.绑定成员函数:为了将成员函数triggerFinder
正确绑定到订阅回调,使用std::bind
的注释行是必要的。 - Subscription Options: Ensure
options
is properly initialized if needed. In this snippet, it is assumed to be a member variable of theGravityDirFinder
class.订阅选项:如果需要,确保options
已正确初始化。在本代码段中,假定它是GravityDirFinder
类的成员变量。 - Callback Parameter: The
triggerFinder
method should accept a parameter of typestd_msgs::msg::String::SharedPtr
to match the message type of the subscription.回调参数:triggerFinder
方法应接受std_msgs::msg::String::SharedPtr
类型的参数,以匹配订阅的消息类型。
This should make the subscription work as intended, triggering the triggerFinder
method when a new message is received on the current_map_file
topic.这将使订阅按预期运行,在 current_map_file
主题收到新消息时触发 triggerFinder
方法。

If you want the triggerFinder
function to remain without arguments, you can use a lambda function in the subscription definition to call triggerFinder
without any arguments. Here's how you can modify your code:如果您希望 triggerFinder
函数不带参数,您可以在订阅定义中使用 lambda 函数来调用 triggerFinder
而不带任何参数。以下是修改代码的方法:
cpp#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "geometry_msgs/msg/twist.hpp"
class GravityDirFinder : public rclcpp::Node
{
public:
GravityDirFinder()
: Node("gravity_dir_finder")
{
map_name_subscriber_ = this->create_subscription<std_msgs::msg::String>(
"current_map_file", 1,
[this](const std_msgs::msg::String::SharedPtr /*msg*/) {
this->triggerFinder();
},
options);
}
private:
void triggerFinder()
{
// keep the robot stationary when collecting IMU data
geometry_msgs::msg::Twist zero_twist;
zero_twist.linear.x = 0.0;
zero_twist.linear.y = 0.0;
zero_twist.linear.z = 0.0;
zero_twist.angular.x = 0.0;
zero_twist.angular.y = 0.0;
zero_twist.angular.z = 0.0;
// Additional code to handle the IMU data
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr map_name_subscriber_;
rclcpp::SubscriptionOptions options; // Initialize options if needed
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<GravityDirFinder>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
Explanation:解释:
- Lambda Function: Instead of directly binding the member function, a lambda function is used in the subscription definition. This lambda captures
this
(the instance of the class) and callstriggerFinder
without passing any arguments.lambda 函数:在订阅定义中使用 lambda 函数,而不是直接绑定成员函数。该 lambda 捕获this
(类的实例)并调用triggerFinder
,而不传递任何参数。 - Ignoring Message Parameter: The lambda function takes the message parameter but does not use it (
/*msg*/
). This allows you to keep thetriggerFinder
function without arguments while still fitting the expected callback signature forcreate_subscription
.忽略消息参数:lambda 函数接收消息参数,但不使用它(/*msg*/
)。这样,您就可以保留不含参数的triggerFinder
函数,同时仍然符合create_subscription
的预期回调签名。
This approach maintains the desired functionality and allows the triggerFinder
method to remain argument-free.这种方法保持了所需的功能,并允许 triggerFinder
方法保持无参数状态。

If you want to avoid using a lambda function and still call triggerFinder
without arguments, you can create an intermediate member function that matches the subscription callback signature and then calls triggerFinder
internally. Here’s how you can achieve this:如果您想避免使用 lambda 函数,而仍然调用 triggerFinder
且不带参数,您可以创建一个与订阅回调签名相匹配的中间成员函数,然后在内部调用 triggerFinder
。下面是实现这一目的的方法:
cpp#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "geometry_msgs/msg/twist.hpp"
class GravityDirFinder : public rclcpp::Node
{
public:
GravityDirFinder()
: Node("gravity_dir_finder")
{
map_name_subscriber_ = this->create_subscription<std_msgs::msg::String>(
"current_map_file", 1,
std::bind(&GravityDirFinder::mapCallback, this, std::placeholders::_1),
options);
}
private:
// Intermediate callback function
void mapCallback(const std_msgs::msg::String::SharedPtr /*msg*/)
{
this->triggerFinder();
}
void triggerFinder()
{
// keep the robot stationary when collecting IMU data
geometry_msgs::msg::Twist zero_twist;
zero_twist.linear.x = 0.0;
zero_twist.linear.y = 0.0;
zero_twist.linear.z = 0.0;
zero_twist.angular.x = 0.0;
zero_twist.angular.y = 0.0;
zero_twist.angular.z = 0.0;
// Additional code to handle the IMU data
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr map_name_subscriber_;
rclcpp::SubscriptionOptions options; // Initialize options if needed
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<GravityDirFinder>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
Explanation:解释:
- Intermediate Callback Function:
mapCallback
is created as an intermediate member function that matches the required callback signature for the subscription. It takes astd_msgs::msg::String::SharedPtr
argument but does not use it.中间回调函数:mapCallback
作为中间成员函数创建,它与订阅所需的回调签名相匹配。它接收std_msgs::msg::String::SharedPtr
参数,但不使用该参数。 - Binding the Intermediate Function:
std::bind
is used to bind themapCallback
function to the subscription.绑定中间函数:std::bind
用于将mapCallback
函数绑定到订阅。 - Calling
triggerFinder
: InsidemapCallback
, thetriggerFinder
method is called without arguments.调用triggerFinder
:在mapCallback
内部,调用triggerFinder
方法时不使用参数。
This approach keeps your triggerFinder
method without arguments and avoids using a lambda function in the subscription.这种方法使您的 triggerFinder
方法不含参数,并避免在订阅中使用 lambda 函数。