ROS2 Basics in 5 Days Humble (C++) course - example 5.2 in Unit 5.2.2

Greetings,

I’m trying to compile the file “action_client.cpp” with example 5.2 in Unit 5.2.2.
The code was same as the exmaple, but I still got the error below:

I found the same error in this page: [ROS2 Foxy] rclcpp_action "no match for ‘operator=’ " - ROS Answers: Open Source Q&A Forum

But the code in the file “action_client.cpp” has already used “SharedPtr”.

Is the system error or something else?

Hi @kjoelovelife,

i have the same problem after trying to compile the example code!

Hi @kjoelovelife and @mosgaed ,

I just tried to compile and execute that code. It is working fine for me.
But I tried on the ROS2 Basics in 5 Days (C++) course. The course states that it will be deprecated on Jan 13, 2023.
I did not try this out on the Humble version yet.

Are you guys on the ROS2 Basics in 5 Days (C++) course or ROS2 Basics in 5 Days Humble (C++) course?

Regards,
Girish

Hi @girishkumar.kannan,

I do the ROS Basics in 5 Days Humble (C++) Course.

Hi @mosgaed and @girishkumar.kannan

I have the same mistake on ROS Basics in 5 Days Humble (C++)

Hi @girishkumar.kannan
I do the ROS2 Basics in 5 Days Humble (C++) course too, sorry I posted the wrong title.

Hi @kjoelovelife , @mosgaed , @Voltedge ,

Just working on that package - you don’t get that single error. There is a bunch of errors and warnings.

user:~/ros2_ws$ colcon build --packages-select my_action_client
Starting >>> my_action_client
[Processing: my_action_client]
--- stderr: my_action_client
/home/user/ros2_ws/src/my_action_client/src/action_client.cpp: In member function 'void MyActionClient::send_goal()':
/home/user/ros2_ws/src/my_action_client/src/action_client.cpp:61:66: error: no match for 'operator=' (operand types are 'rclcpp_action::Client<t3_action_msg::action::Move>::GoalResponseCallback' {aka 'std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>'} and 'std::_Bind_helper<false, void (MyActionClient::*)(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >), MyActionClient*, const std::_Placeholder<1>&>::type')
   61 |       std::bind(&MyActionClient::goal_response_callback, 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/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/detail/move__struct.hpp:8,
                 from /home/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/move.hpp:7,
                 from /home/user/ros2_ws/src/my_action_client/src/action_client.cpp:6:
/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<t3_action_msg::action::Move> >}]'
  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/stl_pair.h:59,
                 from /usr/include/c++/11/bits/stl_algobase.h:64,
                 from /usr/include/c++/11/memory:63,
                 from /home/user/ros2_ws/src/my_action_client/src/action_client.cpp:2:
/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<t3_action_msg::action::Move> >)>&]':
/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<t3_action_msg::action::Move> >)>::_Callable<std::_Bind<void (MyActionClient::*(MyActionClient*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >)>, std::_Bind<void (MyActionClient::*(MyActionClient*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >)>, std::__invoke_result<std::_Bind<void (MyActionClient::*(MyActionClient*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move>> >)>&, std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > > >; _Tp = std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>&; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >}]'
/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<t3_action_msg::action::Move> >)>::_Requires<std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>::_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<t3_action_msg::action::Move> >)> >::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<t3_action_msg::action::Move> >)> >::value), std::decay<_Tp> >::type::type&, std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > > >, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>&> std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>::operator=<_Functor>(_Functor&&) [with _Functor = std::_Bind<void (MyActionClient::*(MyActionClient*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >)>]'
/home/user/ros2_ws/src/my_action_client/src/action_client.cpp:61:66:   required from here
/usr/include/c++/11/type_traits:2211:11: error: no type named 'type' in 'struct std::enable_if<false, std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>&>'
 2211 |     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/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/detail/move__struct.hpp:8,
                 from /home/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/move.hpp:7,
                 from /home/user/ros2_ws/src/my_action_client/src/action_client.cpp:6:
/usr/include/c++/11/bits/std_function.h:540:9: note: candidate: 'template<class _Functor> std::function<_Res(_ArgTypes ...)>&std::function<_Res(_ArgTypes ...)>::operator=(std::reference_wrapper<_Functor>) [with _Functor = _Functor; _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >}]'
  540 |         operator=(reference_wrapper<_Functor> __f) noexcept
      |         ^~~~~~~~
/usr/include/c++/11/bits/std_function.h:540:9: note:   template argument deduction/substitution failed:
/home/user/ros2_ws/src/my_action_client/src/action_client.cpp:61:66: note:   'std::_Bind<void (MyActionClient::*(MyActionClient*, std::_Placeholder<1>))(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >)>' is not derived from 'std::reference_wrapper<_Tp>'
   61 |       std::bind(&MyActionClient::goal_response_callback, 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/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/detail/move__struct.hpp:8,
                 from /home/simulations/ros2_sims_ws/install/t3_action_msg/include/t3_action_msg/t3_action_msg/action/move.hpp:7,
                 from /home/user/ros2_ws/src/my_action_client/src/action_client.cpp:6:
/usr/include/c++/11/bits/std_function.h:469:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >}]'
  469 |       operator=(const function& __x)
      |       ^~~~~~~~
/usr/include/c++/11/bits/std_function.h:469:33: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, void (MyActionClient::*)(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >), MyActionClient*, const std::_Placeholder<1>&>::type' to 'const std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>&'
  469 |       operator=(const function& __x)
      |                 ~~~~~~~~~~~~~~~~^~~
/usr/include/c++/11/bits/std_function.h:487:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >}]'
  487 |       operator=(function&& __x) noexcept
      |       ^~~~~~~~
/usr/include/c++/11/bits/std_function.h:487:28: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, void (MyActionClient::*)(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >), MyActionClient*, const std::_Placeholder<1>&>::type' to 'std::function<void(std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >)>&&'
  487 |       operator=(function&& __x) noexcept
      |                 ~~~~~~~~~~~^~~
/usr/include/c++/11/bits/std_function.h:501:7: note: candidate: 'std::function<_Res(_ArgTypes ...)>& std::function<_Res(_ArgTypes ...)>::operator=(std::nullptr_t) [with _Res = void; _ArgTypes = {std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> >}; std::nullptr_t = std::nullptr_t]'
  501 |       operator=(nullptr_t) noexcept
      |       ^~~~~~~~
/usr/include/c++/11/bits/std_function.h:501:17: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, void (MyActionClient::*)(std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<t3_action_msg::action::Move> > >), MyActionClient*, const std::_Placeholder<1>&>::type' to 'std::nullptr_t'
  501 |       operator=(nullptr_t) noexcept
      |                 ^~~~~~~~~
gmake[2]: *** [CMakeFiles/action_client_node.dir/build.make:76: CMakeFiles/action_client_node.dir/src/action_client.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:137: CMakeFiles/action_client_node.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
---
Failed   <<< my_action_client [30.0s, exited with code 2]

Summary: 0 packages finished [31.2s]
  1 package failed: my_action_client
  1 package had stderr output: my_action_client

I am working on this now to find a fix. If I can fix it, I will keep you guys updated.

Regards,
Girish

Hi @kjoelovelife , @mosgaed , @Voltedge ,

Good News: I have solved this problem! (Let me know if you need my full code.)
Bad News (probably, not sure): It may not be the best solution, but this still works - I have tested this with a couple of examples.

I did quite some research to figure this out. Here are some links for you guys to educate yourself:

  1. goal_response_callback
  2. NewSignature
  3. GoalResponseCallback with NewSignature

Note: The above links are from Galactic version. Documentation pages for Humble does not exist yet! [Replacing “galactic” to “humble” in the above links takes to “page not found”.]

Now, the Solution:

Replace the following function / code:

void goal_response_callback(std::shared_future<GoalHandleMove::SharedPtr> future) {
  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");
  }
}

With this function / code:

void goal_response_callback(GoalHandleMove::SharedPtr goal_handle) {
  if (goal_handle == nullptr) {
    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(): Takes a single argument that is a goal handle shared pointer. If the goal is accepted, then the pointer points to a valid goal handle. If the goal is rejected, then pointer has the value nullptr . Source: Refer Link 1 above.

@albertoezquerro : Please validate my research and the solution I have provided here. This solution works - but I am not sure if this is “The Best Solution” for this problem. Thanks!

Regards,
Girish

Here is the proof of output:

1 Like

Hi @girishkumar.kannan,

Great Work! That works for me! I think this is the right solution, maybe they removed the old signature in the Humble version and replaced it as default with the new signature.

1 Like

Hi @girishkumar.kannan, @kjoelovelife, @Voltedge

I researched in the official ROS2 Humble documentation for the action service client. In the example code they also use the NewSignature as mentioned from @girishkumar.kannan.

image

Link for the Humble Documentation: Writing an action server and client (C++) — ROS 2 Documentation: Humble documentation

but in ths example they are using a const shared pointer.

Hi @mosgaed ,

Wow! I did check the same page. I can’t believe that I overlooked this function definition! My bad!

Anyways, glad you have found it!

@albertoezquerro : Please make the changes in the course notes when you find time. Thanks!

Regards,
Girish

Hello everyone!

First of all, many thanks to @girishkumar.kannan for reacting so fast and so well to the issue. Great work!

I’ve been investigating and testing myself and the correct solution is the one presented by @mosgaed in his last post. I’ve already pushed the changes to the notebook to show the updated code for the action client.

1 Like

That is because https://docs.ros2.org/ is deprecated.
Links to the API documentation of packages can now be found through the ROS Index.
E.g. for rclcpp_action see this package info page. At the top right you can find the link to the API documentation.

Regards,
Johan

Hi @JRTG ,

Thanks a lot for sharing this info! I never knew about ROS Index, perhaps because I have not moved to Humble yet.
Finally, I can see a clean and well explained documentation that also looks pretty!

The main link to the API on README.md still takes me to docs.ros2.org.
Clicking on “API Docs” on the top right takes me to the better looking documentation page.

– Girish

Indeed…

It’s because the readme’s haven’t been updated in github.
If you feel like it, you can provide a pull request to change it…
Or create an issue.

Re,
Johan

Wow! Great works! Thanks @girishkumar.kannan took the solution first, @mosgaed offered the official document, and @albertoezquerro update the code.

Thanks again and a lot! Wish everyone here has a nice day!

Hi @kjoelovelife ,

The actual solution is the one posted by @mosgaed , the picture to the documentation code.

I request that you change the solution to the above post, so that people who (might) see this post in the future will not be tempted to copy-paste my solution.

Regards,
Girish

Hi @girishkumar.kannan , I have changed the solution.
Thanks.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.