小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
关于ros2 action发布时回调函数的模板函数格式问题
-
最近在写一个c++节点需要发布目标点使用nav2导航至该目标,但是当我写到`send_goal_options.goal_response_callbac``这个回调函数时,出现了问题,编译器显示
/home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:75:172: error: no match for ‘operator=’ (operand types are ‘rclcpp_action::Client<nav2_msgs::action::NavigateToPose>::GoalResponseCallback’ {aka ‘std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>’} and ‘std::_Bind_helper<false, void (hoist_decision::*)(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >), hoist_decision*, const std::_Placeholder<1>&>::type’) 75 | GoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr>>, this, _1 ); | ^ In file included from /usr/include/c++/11/functional:59, from /usr/include/c++/11/pstl/glue_algorithm_defs.h:13, from /usr/include/c++/11/algorithm:74, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:3: /usr/include/c++/11/bits/std_function.h:530:9: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<_Functor>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = _Functor; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >}]’ 530 | operator=(_Functor&& __f) | ^~~~~~~~ /usr/include/c++/11/bits/std_function.h:530:9: note: template argument deduction/substitution failed: In file included from /usr/include/c++/11/bits/move.h:57, from /usr/include/c++/11/bits/exception_ptr.h:43, from /usr/include/c++/11/exception:153, from /usr/include/c++/11/ios:39, from /usr/include/c++/11/ostream:38, from /usr/include/c++/11/iostream:39, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:1: /usr/include/c++/11/type_traits: In substitution of ‘template<bool _Cond, class _Tp> using __enable_if_t = typename std::enable_if::type [with bool _Cond = false; _Tp = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&]’: /usr/include/c++/11/bits/std_function.h:353:8: required by substitution of ‘template<class _Res, class ... _ArgTypes> template<class _Cond, class _Tp> using _Requires = std::__enable_if_t<_Cond::value, _Tp> [with _Cond = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Callable<std::_Bind<void (hoist_decision::*(hoist_decision*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>, std::_Bind<void (hoist_decision::*(hoist_decision*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>, std::__invoke_result<std::_Bind<void (hoist_decision::*(hoist_decision*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>&, std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > > >; _Tp = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >}]’ /usr/include/c++/11/bits/std_function.h:530:2: required by substitution of ‘template<class _Functor> std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Requires<std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Callable<_Functor, typename std::enable_if<(! std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)> >::value), std::decay<_Tp> >::type::type, std::__invoke_result<typename std::enable_if<(! std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)> >::value), std::decay<_Tp> >::type::type&, std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > > >, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&> std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::operator=<_Functor>(_Functor&&) [with _Functor = std::_Bind<void (hoist_decision::*(hoist_decision*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>]’ /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:75:172: required from here /usr/include/c++/11/type_traits:2205:11: error: no type named ‘type’ in ‘struct std::enable_if<false, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&>’ 2205 | using __enable_if_t = typename enable_if<_Cond, _Tp>::type; | ^~~~~~~~~~~~~ In file included from /usr/include/c++/11/functional:59, from /usr/include/c++/11/pstl/glue_algorithm_defs.h:13, from /usr/include/c++/11/algorithm:74, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:3:
其中相关代码是这样的
std::bindsend_goal_options.goal_response_callback = std::bind(&hoist_decision::goal_response_callback<std::shared_future<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr>>, this, _1 );
这个是我的回调函数
template<typename T> void goal_response_callback(T future) { if (debug) { // RCLCPP_INFO(this->get_logger(), "In task %s response callback",server_names[current_executing]); auto goal_handle = future.get(); if (!goal_handle) { RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server"); } else { RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result"); } } }
看编译器中的报错,似乎是我的回调函数不对,但是我实在找不到如何改正。希望有人能给我一些意见。
顺带一提,我在CMakeList中指定了C++14来编译set(CMAKE_CXX_STANDARD 14)
,但是这个报错似乎显示依然是用C++11,不知道时不是这个原因。 -
从您提供的错误信息来看,问题出在尝试将
std::bind
的结果赋值给rclcpp_action::Client<>::GoalResponseCallback
类型的成员变量上,而std::bind
返回的是一个不可转换为std::function
的绑定对象(特别是当涉及到模板和完美转发时)。此外,您使用的模板函数goal_response_callback
在std::bind
的上下文中也没有正确地指定模板参数。在ROS 2中,您应该使用lambda表达式来代替
std::bind
,因为lambda表达式与std::function
的兼容性更好,并且更易于理解和使用。这里是一个使用lambda表达式来设置
goal_response_callback
的例子:send_goal_options.goal_response_callback = [this](std::shared_future<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr> future) { this->goal_response_callback_helper(future); }; // 辅助函数,用于处理回调,避免在lambda中直接写太多代码 template<typename T> void goal_response_callback_helper(T future) { if (debug) { // ...(您的日志代码) auto goal_handle = future.get(); if (!goal_handle) { RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server"); } else { RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result"); } } }
请注意,我创建了一个名为
goal_response_callback_helper
的辅助函数来处理实际的回调逻辑,因为lambda表达式内不适合直接写大量代码。另外,由于lambda表达式已经捕获了this
指针,因此可以直接在lambda内部调用类的成员函数。关于C++标准的问题,虽然您设置了
CMAKE_CXX_STANDARD 14
,但错误消息中显示的路径和错误类型通常与C++11相关。这可能是因为ROS 2的某些部分或依赖项仍然使用C++11。然而,这不太可能是您遇到的主要问题,因为lambda表达式和std::function
在C++11中就已经是可用的了。如果上述解决方案不起作用,或者您遇到其他编译错误,请检查ROS 2文档以确保您的代码与ROS 2的API兼容,并考虑升级您的ROS 2版本(如果可能的话)。
以上为生成回答,仅供参考~
-
@小伊 在 关于ros2 action发布时回调函数的模板函数格式问题 中说:
send_goal_options.goal_response_callback =
[this](std::shared_future<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr> future) {
this->goal_response_callback_helper(future);
};不对,这样修改后报错还是大同小异,不能解决我的问题
/home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:79:13: error: no match for ‘operator=’ (operand types are ‘rclcpp_action::Client<nav2_msgs::action::NavigateToPose>::GoalResponseCallback’ {aka ‘std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>’} and ‘hoist_decision::GoToPose(geometry_msgs::msg::Pose_<std::allocator<void> >::SharedPtr, int, int)::<lambda(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>’) 79 | }; | ^ In file included from /usr/include/c++/11/functional:59, from /usr/include/c++/11/pstl/glue_algorithm_defs.h:13, from /usr/include/c++/11/algorithm:74, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:3: /usr/include/c++/11/bits/std_function.h:530:9: note: candidate: ‘template<class _Functor> std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<_Functor>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = _Functor; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >}]’ 530 | operator=(_Functor&& __f) | ^~~~~~~~ /usr/include/c++/11/bits/std_function.h:530:9: note: template argument deduction/substitution failed: In file included from /usr/include/c++/11/bits/move.h:57, from /usr/include/c++/11/bits/exception_ptr.h:43, from /usr/include/c++/11/exception:153, from /usr/include/c++/11/ios:39, from /usr/include/c++/11/ostream:38, from /usr/include/c++/11/iostream:39, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:1: /usr/include/c++/11/type_traits: In substitution of ‘template<bool _Cond, class _Tp> using __enable_if_t = typename std::enable_if::type [with bool _Cond = false; _Tp = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&]’: /usr/include/c++/11/bits/std_function.h:353:8: required by substitution of ‘template<class _Res, class ... _ArgTypes> template<class _Cond, class _Tp> using _Requires = std::__enable_if_t<_Cond::value, _Tp> [with _Cond = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Callable<hoist_decision::GoToPose(geometry_msgs::msg::Pose_<std::allocator<void> >::SharedPtr, int, int)::<lambda(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>, hoist_decision::GoToPose(geometry_msgs::msg::Pose_<std::allocator<void> >::SharedPtr, int, int)::<lambda(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>, std::__invoke_result<hoist_decision::GoToPose(geometry_msgs::msg::Pose_<std::allocator<void> >::SharedPtr, int, int)::<lambda(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>&, std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > > >; _Tp = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >}]’ /usr/include/c++/11/bits/std_function.h:530:2: required by substitution of ‘template<class _Functor> std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Requires<std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::_Callable<_Functor, typename std::enable_if<(! std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)> >::value), std::decay<_Tp> >::type::type, std::__invoke_result<typename std::enable_if<(! std::is_same<typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)> >::value), std::decay<_Tp> >::type::type&, std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > > >, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&> std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>::operator=<_Functor>(_Functor&&) [with _Functor = hoist_decision::GoToPose(geometry_msgs::msg::Pose_<std::allocator<void> >::SharedPtr, int, int)::<lambda(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> > >)>]’ /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:79:13: required from here /usr/include/c++/11/type_traits:2205:11: error: no type named ‘type’ in ‘struct std::enable_if<false, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose> >)>&>’ 2205 | using __enable_if_t = typename enable_if<_Cond, _Tp>::type; | ^~~~~~~~~~~~~ In file included from /usr/include/c++/11/functional:59, from /usr/include/c++/11/pstl/glue_algorithm_defs.h:13, from /usr/include/c++/11/algorithm:74, from /home/vr/ros2_hoist/src/hoist_decision/src/hoist_decision.cpp:3:
-
这个错误是因为你试图将一个 lambda 表达式赋值给一个
rclcpp_action::ClientGoalHandle
类型的std::function
回调,但是 lambda 表达式的参数类型与std::function
所期望的参数类型不匹配。在你的代码中,lambda 表达式是这样的:
[this](std::shared_future<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr> future) { this->goal_response_callback_helper(future); };
而
rclcpp_action::Client<nav2_msgs::action::NavigateToPose>::GoalResponseCallback
应该是一个接受std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>>
的std::function
。但是,你的 lambda 表达式中接受的是
std::shared_future
的一个模板实例,而不是直接接受std::shared_ptr
。要修复这个错误,你需要确保 lambda 表达式的参数类型与
rclcpp_action::Client
所期望的回调类型相匹配。由于rclcpp_action::Client
并不直接处理std::shared_future
,你应该使用一个std::shared_ptr
而不是std::shared_future
。如果你需要在回调函数中使用
std::shared_future
(这通常不是rclcpp_action
的标准用法),你可能需要改变你的设计,以便回调函数能够访问包含std::shared_future
的某个对象或状态。但是,在大多数情况下,你应该直接传递
std::shared_ptr
,如下所示:send_goal_options.goal_response_callback = [this](std::shared_ptr<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>> goal_handle) { // 你的回调函数逻辑,这里可以使用 goal_handle this->goal_response_callback_helper(goal_handle); };
请注意,我将
std::shared_future
替换为std::shared_ptr<rclcpp_action::ClientGoalHandle<...>>
。确保你的
goal_response_callback_helper
函数也接受相同类型的参数。如果它确实需要std::shared_future
(这通常不是 ROS 2 actions 的情况),你需要重新设计你的代码以适应这一点。
以上为生成回答,仅供参考~
-
std::bind(&hoist_decision::goal_response_callback<std::shared_future<rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::SharedPtr>>, this, _1 );
这个代码的长度真是糟糕啊 -
@minemyemails 确实是这样的,但是模板定义就这么长。
不过我这个错误解决不掉,改用普通函数了 -
-
@小鱼 太好了,可惜才看到 。
-
@小鱼 这个cookboot很好啊,之前怎么没宣传一下。之前看到你的教学中有提到一个cookbook,但好像点不进去
-
@小鱼 发现是新书中的代码,快快出书吧
-
@2429148505 在预售了,预计8月中旬到货,等我店里上架,会更便宜点,已经要求编辑按最低价格定价了