/home/jian/laser_ws/src/laser_node/src/laser_node.cpp: In constructor ‘laser_node::laser_node(const char*)’: /home/jian/laser_ws/src/laser_node/src/laser_node.cpp:32:10: error: no matching function for call to ‘laser_node::create_subscription(std::string, int, laser_node::laser_node(const char*)::<lambda()>)’ 32 | }); | ^ In file included from /opt/ros/foxy/include/rclcpp/executors/single_threaded_executor.hpp:28, from /opt/ros/foxy/include/rclcpp/executors.hpp:22, from /opt/ros/foxy/include/rclcpp/rclcpp.hpp:146, from /home/jian/laser_ws/src/laser_node/src/laser_node.cpp:11: /opt/ros/foxy/include/rclcpp/node.hpp:213:3: note: candidate: ‘template<class MessageT, class CallbackT, class AllocatorT, class CallbackMessageT, class SubscriptionT, class MessageMemoryStrategyT> std::shared_ptr<SubscriptionT> rclcpp::Node::create_subscription(const string&, const rclcpp::QoS&, CallbackT&&, const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>&, typename MessageMemoryStrategyT::SharedPtr)’ 213 | create_subscription( | ^~~~~~~~~~~~~~~~~~~ /opt/ros/foxy/include/rclcpp/node.hpp:213:3: note: template argument deduction/substitution failed: /home/jian/laser_ws/src/laser_node/src/laser_node.cpp:32:10: note: couldn’t deduce template parameter ‘MessageT’ 32 | }); | ^ make[2]: *** [CMakeFiles/laser_node.dir/build.make:63:CMakeFiles/laser_node.dir/src/laser_node.cpp.o] 错误 1 make[1]: *** [CMakeFiles/Makefile2:78:CMakeFiles/laser_node.dir/all] 错误 2 make: *** [Makefile:141:all] 错误 2
时间: 2025-07-31 15:40:47 浏览: 15
<think>我们正在处理一个关于ROS2 C++节点编译错误的问题。用户遇到了“无法推导出create_subscription的模板参数”的错误。
错误信息表明编译器无法自动推导出模板参数,因此我们需要显式指定模板参数。
在ROS2中,`create_subscription`函数的典型用法如下:
```cpp
auto subscription = node->create_subscription<message_type>(
"topic_name",
10,
[](const message_type::SharedPtr msg) { /* 处理消息 */ });
```
如果模板参数(即消息类型)没有正确指定,或者回调函数的签名与消息类型不匹配,就会导致此类错误。
根据用户提供的错误信息,我们需要检查以下几点:
1. 是否在调用`create_subscription`时显式指定了消息类型?
2. 回调函数的参数类型是否与指定的消息类型匹配?
3. 是否包含了正确的头文件?
另外,参考用户提供的引用(虽然来自action,但原理相似)中使用了`std::shared_future`等,但这里的问题是关于subscription的。
解决方案:
步骤1:显式指定消息类型
在`create_subscription`的尖括号中明确写出消息类型,例如`<std_msgs::msg::String>`。
步骤2:确保回调函数签名正确
回调函数通常接受一个消息类型的常量共享指针,例如`const std_msgs::msg::String::SharedPtr`。
步骤3:检查头文件
确保包含了所需消息类型的头文件,例如`#include <std_msgs/msg/string.hpp>`
示例代码:
```cpp
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class MyNode : public rclcpp::Node {
public:
MyNode() : Node("my_node") {
// 显式指定消息类型为std_msgs::msg::String
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic",
10,
std::bind(&MyNode::topic_callback, this, std::placeholders::_1));
}
private:
void topic_callback(const std_msgs::msg::String::SharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MyNode>());
rclcpp::shutdown();
return 0;
}
```
注意:如果使用lambda表达式,也要确保参数类型正确:
```cpp
auto subscription = create_subscription<std_msgs::msg::String>("topic", 10,
[this](std_msgs::msg::String::ConstSharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
});
```
如果问题仍然存在,请检查ROS2版本和消息包是否安装正确。
相关问题:
1. ROS2中如何正确使用create_subscription?
2. 如何解决ROS2 C++中的模板参数推导失败错误?
3. ROS2消息回调函数的正确签名是什么?</think>### ROS2 C++ create_subscription 模板参数推导失败错误修复
在 ROS2 C++ 中,`create_subscription` 出现模板参数推导失败错误通常是由于编译器无法自动推断回调函数的参数类型导致的。以下是完整解决方案:
#### 错误原因分析
1. **模板参数缺失**:`create_subscription` 需要显式指定消息类型
2. **回调签名不匹配**:回调函数参数类型与订阅消息类型不一致
3. **作用域问题**:类成员函数未正确绑定 `this` 指针
4. **Lambda 捕获错误**:Lambda 表达式未正确捕获类实例
#### 解决方案
##### 1. 显式指定模板参数(推荐)
在调用时显式声明消息类型:
```cpp
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic_name", // 话题名称
10, // 队列长度
[this](const std_msgs::msg::String::SharedPtr msg) { // 正确Lambda
RCLCPP_INFO(this->get_logger(), "Received: %s", msg->data.c_str());
}
);
```
##### 2. 修复类成员回调函数
对于类成员函数,需使用 `std::bind` 绑定 `this`:
```cpp
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic_name",
10,
std::bind(&MyNode::topic_callback, this, std::placeholders::_1)
);
// 类内回调函数声明
void topic_callback(const std_msgs::msg::String::SharedPtr msg);
```
##### 3. 确保消息类型一致性
检查头文件包含和消息类型:
```cpp
#include "std_msgs/msg/string.hpp" // 必须包含对应消息头文件
// 使用全限定类型名避免歧义
using std_msgs::msg::String;
```
#### 完整示例代码
```cpp
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class MyNode : public rclcpp::Node {
public:
MyNode() : Node("my_node") {
// 正确用法:显式模板参数 + Lambda
subscription_ = this->create_subscription<std_msgs::msg::String>(
"/chatter",
10,
[this](std_msgs::msg::String::ConstSharedPtr msg) {
RCLCPP_INFO(this->get_logger(), "Received: %s", msg->data.c_str());
}
);
}
private:
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
auto node = std::make_shared<MyNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
```
#### 常见错误排查
1. **缺少消息依赖**:在 `package.xml` 中添加:
```xml
<depend>std_msgs</depend>
```
2. **回调签名错误**:确保使用 `::ConstSharedPtr` 或 `::SharedPtr`
3. **C++标准问题**:在 `CMakeLists.txt` 中设置 C++17:
```cmake
set(CMAKE_CXX_STANDARD 17)
```
当编译器无法推导模板参数时,显式指定消息类型是最可靠的解决方案。ROS2 的强类型系统要求精确匹配消息类型,这与动态类型语言如 Python 不同[^1]。
阅读全文
相关推荐


















