How to call action with an empty goal?

Hi,

I’ve tried looking for the solution online and browsing the actions document but I can’t seem to get the action service running by sending the goal through the terminal. Everythings compiled succesfully, and action is running alright, but when I send the goal it just spouts errors.

The custom interface:

                                                           # no goal/ request
---
geometry_msgs/msg/Point32[] list_of_odoms
---
float32 current_total

Compiling the package I get the warning that the goal is unused…

/home/user/ros2_ws/src/wall_follower_pkg/src/odomrecord_server.cpp: In member function 'rclcpp_action::GoalResponse OdomRecordActionServer::handle_goal(const GoalUUID&, std::shared_ptr<const custom_interfaces::action::OdomRecord_Goal_<std::allocator<void> > >)':
/home/user/ros2_ws/src/wall_follower_pkg/src/odomrecord_server.cpp:54:62: warning: unused parameter 'goal' [-Wunused-parameter]
   54 |               std::shared_ptr<const OdomRecord_Action::Goal> goal) {

so I’ve tried removing it and playing around with it but still couldn’t get it right:

private:
  rclcpp_action::GoalResponse
  handle_goal(const rclcpp_action::GoalUUID &uuid,
              std::shared_ptr<const OdomRecord_Action::Goal> goal) {
    // response to receiving goal
    RCLCPP_INFO(this->get_logger(), "Received goal: Record Odometry");
    (void)uuid;
    return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
  }

and

private:
  rclcpp_action::GoalResponse
  handle_goal(const rclcpp_action::GoalUUID &uuid) {
    // response to receiving goal
    RCLCPP_INFO(this->get_logger(), "Received goal: Record Odometry");
    (void)uuid;
    return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
  }

I havent created a client yet because I want to test that this is working as I expected through the terminal first so I have sent the goal using:

ros2 action send_goal /record_odom custom_interfaces/action/OdomRecord 

and

ros2 action send_goal /record_odom custom_interfaces/action/OdomRecord "{  }"

but it’s saying it AttributeError: 'ActionClient' object has no attribute '_client_handle'. Does this mean i need to create the client and sending an empty goal through the terminal won’t work but through the client it will?

I’m not looking for the complete answer but can I get some hints for this part of the project please?

***EDIT: I found out you can use axclient to test the server? but I don’t find any methods for running this axclient stuff for ROS2 in the terminal. Are there no examples?

Many Thanks for the help,
William

Hi @william.lubiantoro,

Could it be that you are trying to use the action client before calling rclpy.init()?

Here are some things you could try:

  1. Make sure you have initialized the action client properly using rclpy.init() before creating an instance of the ActionClient class.

  2. Check that you have created an instance of the ActionClient class and that it is still in scope and not destroyed when you are trying to access its methods or attributes.

  3. Verify that you are using the correct syntax to access the methods or attributes of the ActionClient class. For example, you should use action_client.send_goal() to send a goal, rather than accessing _client_handle directly.

If you are still encountering the error after checking the above points, please provide more context or code snippets of how you are using the action client so that we can provide more specific guidance.

Hi @ralves,

Thank you for your reply, as mentioned before, I have not created an action client as I wanted to test the server using the terminal before creating the client. Do I have to create the client to call an action service that has blank as a goal?

I will try to create an action client.

Hi @william.lubiantoro

No, you don’t need to write a client to test out the action server. You can test it out on the terminal.

Assuming that the action has been properly defined and is running, you should be able to get the structure auto-filled by running:

ros2 action send_goal /record_odom [TAB] [TAB]    # press the tab twice is quick succession

Hi @bayodesegun,

Thank you for the response, the action server has been called succesfully and is now working as intended.

I am now creating the client and am getting this error from the following line because the goal is a blank.:

send_goal_options.goal_response_callback =
        std::bind(&OdomRecordActionClient::goal_response_callback, this, _1);

It works in the terminal but from the client it is giving this error:

No viable overloaded '='clang(ovl_no_viable_oper)
std_function.h(462, 7): Candidate function not viable: no known conversion from 'typename _Bind_helper<__is_socketlike<void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &)>::value, void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &), OdomRecordActionClient *, const _Placeholder<1> &>::type' (aka '_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)>') to 'const std::function<void (std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>>>)>' for 1st argument
std_function.h(480, 7): Candidate function not viable: no known conversion from 'typename _Bind_helper<__is_socketlike<void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &)>::value, void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &), OdomRecordActionClient *, const _Placeholder<1> &>::type' (aka '_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)>') to 'std::function<void (std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>>>)>' for 1st argument
std_function.h(494, 7): Candidate function not viable: no known conversion from 'typename _Bind_helper<__is_socketlike<void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &)>::value, void (OdomRecordActionClient::*)(const shared_ptr<ClientGoalHandle<OdomRecord>> &), OdomRecordActionClient *, const _Placeholder<1> &>::type' (aka '_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)>') to 'std::nullptr_t' for 1st argument
std_function.h(523, 2): Candidate template ignored: requirement '_Callable<std::_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)>, std::__invoke_result<std::_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)> &, std::shared_future<std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>>>>>::value' was not satisfied [with _Functor = std::_Bind<void (OdomRecordActionClient::*(OdomRecordActionClient *, std::_Placeholder<1>))(const std::shared_ptr<rclcpp_action::ClientGoalHandle<custom_interfaces::action::OdomRecord>> &)>]
std_function.h(532, 2): Candidate template ignored: could not match 'reference_wrapper' against '_Bind'

In the send_goal function I have:

void send_goal() {
    using namespace std::placeholders;

    this->timer_->cancel();

    if (!this->odomrec_actionclient_) {
      // check if action server is running
      RCLCPP_ERROR(this->get_logger(), "Action client not initialized");
    }

    if (!this->odomrec_actionclient_->wait_for_action_server()) {
      RCLCPP_ERROR(this->get_logger(),
                   "Action server not available after waiting");
      rclcpp::shutdown();
    }

    auto goal_msg = OdomRecord::Goal();
    RCLCPP_INFO(this->get_logger(), "Sending goal: Record Odom");
    auto send_goal_options =
        rclcpp_action::Client<OdomRecord>::SendGoalOptions();
    send_goal_options.goal_response_callback =
        std::bind(&OdomRecordActionClient::goal_response_callback, this, _1);
    send_goal_options.feedback_callback =
        std::bind(&OdomRecordActionClient::feedback_callback, this, _1, _2);
    send_goal_options.result_callback =
        std::bind(&OdomRecordActionClient::result_callback, this, _1);
    this->odomrec_actionclient_->async_send_goal(goal_msg, send_goal_options);
  }

I have the goal_msg variable but it doesn’t really have anything…

I understand that the error comes from having the goal as blank but I’m still technically sending a goal and calling the server. Can I get advice on how this could be fixed? or which part of the code should I look to change?

Many Thanks in advance,
William L.

Hi @bayodesegun,

No worries I found the problem, it might just be false-positive error not in the compiler.

William

Great! Glad you got it working. Do you mind telling us what you did differently? Recompiled?

I was looking for that specific error and found this link and this link that had the same problem with a solution :).

As for the first problem with sending the goal as a blank through the terminal with ros2 action send_goal /record_odom [TAB] [TAB] not working, I searched and found out that the dependencies geometry_msgs is required in the custom_interfaces Cmake file. Initially I read somewhere it was better without the DEPENDENCIES but turns out you need it for this specific one. I wonder why…?

Many Thanks though :).

Cheers!

Good job!

You should include it as a dependency since you used it in your custom message definition. There is no penalty for including a message, even if it’s not needed. I would even include std_msgs, because of the float32

Thank you @bayodesegun!

I have since then completed the real robot project and tested that it works with the real robot in the lab. I read in the C++ course that I’m supposed to get a certificate… do you know anything about this? Do I get this for completing the real robot project or the course because for the first topics quiz I got a 0/10 due to misclicking the submit and view the answers/code button.

William

Please send an email to info at theconstructsim dot com to schedule your presentation.

From what I can see on the course details pages, by clicking the Show my Scores! button, only the Real Robot Project is required to obtain the certificate. Lucky you :wink:.

Thank you very much.

1 Like

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