Not exactly the expected execution action client Example 6.2.2 ros basics c++

Hello there,

Can somebody explain me why the Example 6.2.2 of the ros2 basics in5 days (c++) doesn’t end cleanly alone like in the example?

It seems that the execution of the condition around the spin doesn’t work.

Can somebody explain it to me please?
Thank you in advance

  while (!action_client->is_goal_done()) {
    executor.spin();
  }

my shell

user:~/ros2_ws$ ros2 launch my_action_client action_client.launch.py
[INFO] [launch]: All log files can be found below /home/user/.ros/log/2023-06-30-13-38-58-147029-3_xterm-31256
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [action_client_node-1]: process started with pid [31257]
[action_client_node-1] [INFO] [1688132338.835004777] [my_action_client]: Sending goal
[action_client_node-1] [INFO] [1688132338.837595739] [my_action_client]: Goal accepted by server, waiting for result
[action_client_node-1] [INFO] [1688132338.837897867] [my_action_client]: Feedback received: Moving to the left left left...
[action_client_node-1] [INFO] [1688132339.837811733] [my_action_client]: Feedback received: Moving to the left left left...
[action_client_node-1] [INFO] [1688132340.837849530] [my_action_client]: Feedback received: Moving to the left left left...
[action_client_node-1] [INFO] [1688132341.837775844] [my_action_client]: Feedback received: Moving to the left left left...
[action_client_node-1] [INFO] [1688132342.838064816] [my_action_client]: Feedback received: Moving to the left left left...
[action_client_node-1] [INFO] [1688132343.837879014] [my_action_client]: Result received: Finished action server. Robot moved during 5 seconds

expected output (example given in the course)

[INFO] [launch]: All log files can be found below /home/user/.ros/log/2022-09-23-10-15-32-814607-3_xterm-54762
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [action_client_node-1]: process started with pid [54788]
[action_client_node-1] [INFO] [1663928134.022203741] [my_action_client]: Sending goal
[action_client_node-1] [INFO] [1663928134.025064408] [my_action_client]: Goal accepted by server, waiting for result
[action_client_node-1] [INFO] [1663928134.032633262] [my_action_client]: Feedback received: Movint to the left left left...
[action_client_node-1] [INFO] [1663928135.035995103] [my_action_client]: Feedback received: Movint to the left left left...
[action_client_node-1] [INFO] [1663928136.036014523] [my_action_client]: Feedback received: Movint to the left left left...
[action_client_node-1] [INFO] [1663928137.033550116] [my_action_client]: Feedback received: Movint to the left left left...
[action_client_node-1] [INFO] [1663928138.032438502] [my_action_client]: Feedback received: Movint to the left left left...
[action_client_node-1] [INFO] [1663928139.033699349] [my_action_client]: Result received: Finished action server. Robot moved during 5 seconds
[INFO] [action_client_node-1]: process has finished cleanly [pid 54788]
#include <inttypes.h>
#include <memory>
#include <string>
#include <iostream>

#include "t3_action_msg/action/move.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_action/rclcpp_action.hpp"

class MyActionClient : public rclcpp::Node
{
public:
  using Move = t3_action_msg::action::Move;
  using GoalHandleMove = rclcpp_action::ClientGoalHandle<Move>;

  explicit MyActionClient(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
  : Node("my_action_client", node_options), goal_done_(false)
  {
    this->client_ptr_ = rclcpp_action::create_client<Move>(
      this->get_node_base_interface(),
      this->get_node_graph_interface(),
      this->get_node_logging_interface(),
      this->get_node_waitables_interface(),
      "move_robot_as");

    this->timer_ = this->create_wall_timer(
      std::chrono::milliseconds(500),
      std::bind(&MyActionClient::send_goal, this));
  }

  bool is_goal_done() const
  {
    return this->goal_done_;
  }

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

    this->timer_->cancel();

    this->goal_done_ = false;

    if (!this->client_ptr_) {
      RCLCPP_ERROR(this->get_logger(), "Action client not initialized");
    }

    if (!this->client_ptr_->wait_for_action_server(std::chrono::seconds(10))) {
      RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting");
      this->goal_done_ = true;
      return;
    }

    auto goal_msg = Move::Goal();
    goal_msg.secs = 5;

    RCLCPP_INFO(this->get_logger(), "Sending goal");

    auto send_goal_options = rclcpp_action::Client<Move>::SendGoalOptions();
                
    send_goal_options.goal_response_callback =
      std::bind(&MyActionClient::goal_response_callback, this, _1);

    send_goal_options.feedback_callback =
      std::bind(&MyActionClient::feedback_callback, this, _1, _2);

    send_goal_options.result_callback =
      std::bind(&MyActionClient::result_callback, this, _1);
      
    auto goal_handle_future = this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
  }

private:
  rclcpp_action::Client<Move>::SharedPtr client_ptr_;
  rclcpp::TimerBase::SharedPtr timer_;
  bool goal_done_;

  void goal_response_callback(const GoalHandleMove::SharedPtr & goal_handle)
  {
    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");
    }
  }

  void feedback_callback(
    GoalHandleMove::SharedPtr,
    const std::shared_ptr<const Move::Feedback> feedback)
  {
    RCLCPP_INFO(
      this->get_logger(), "Feedback received: %s", feedback->feedback.c_str());
  }

  void result_callback(const GoalHandleMove::WrappedResult & result)
  {
    this->goal_done_ = true;
    switch (result.code) {
      case rclcpp_action::ResultCode::SUCCEEDED:
        break;
      case rclcpp_action::ResultCode::ABORTED:
        RCLCPP_ERROR(this->get_logger(), "Goal was aborted");
        return;
      case rclcpp_action::ResultCode::CANCELED:
        RCLCPP_ERROR(this->get_logger(), "Goal was canceled");
        return;
      default:
        RCLCPP_ERROR(this->get_logger(), "Unknown result code");
        return;
    }

    RCLCPP_INFO(this->get_logger(), "Result received: %s", result.result->status.c_str());

  }
};  // class MyActionClient

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);
  auto action_client = std::make_shared<MyActionClient>();
    
  rclcpp::executors::MultiThreadedExecutor executor;
  executor.add_node(action_client);

  while (!action_client->is_goal_done()) {
    executor.spin();
  }

  rclcpp::shutdown();
  return 0;
}

I found why: it has to be executor.spin_some() .

I think it was just forgotten in the example code.

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