ROS2 Basics C++: Service call not completing after being called by service client

I am working on part 2 of the rosject for the ROS2 Basics in 5 days course. I successfully have my part 1 (wall following) and part 2 (wall finding service) working on their own. I have now modified the wall following node from part 1 to create a wall find client, and call the service from part 2. The code below shows the wall following node, with a call to the wall find service in the constructor for the class. My idea was to put this call in the constructor, so the wall find code only runs once.

The problem I am having is that the call to the wall find service never seems to stop. Once the wall is found, the constructor is finished, an the main body of the code runs which starts the wall following. However, it appears that the robot still tries looking for the wall. This results in the robot not being able to track the wall properly.

Here is the relevant code from my wall follow node. As you can see, in the constructor, a service client is created, and the service is called. Can anybody see why the service call won’t end once the wall is found? Shouldn’t this if statement do just that if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result_future) == rclcpp::FutureReturnCode::SUCCESS) { ? Thanks in advance for your advice!

class WallFollowNode : public rclcpp::Node {

public:
  WallFollowNode() : Node("wall_follow_node") {

    // ...code to create pubs, subs, timers here...

    // Create service client
    rclcpp::Client<custom_interfaces::srv::FindWall>::SharedPtr client =
        this->create_client<custom_interfaces::srv::FindWall>(
            "find_wall_non_block");

    // Call the service once at the beginning
    auto request =
        std::make_shared<custom_interfaces::srv::FindWall::Request>();

    while (!client->wait_for_service(1s)) {
      if (!rclcpp::ok()) {
        RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),
                     "Interrupted while waiting for the service. Exiting.");
        throw std::runtime_error(
            "Interrupted while waiting for the service.");
      }
      RCLCPP_INFO(rclcpp::get_logger("rclcpp"),
                  "service not available, waiting again...");
    }

    auto result_future = client->async_send_request(request);
    // Wait for the result.
    if (rclcpp::spin_until_future_complete(this->get_node_base_interface(),
                                           result_future) ==
        rclcpp::FutureReturnCode::SUCCESS) {
      auto result = result_future.get();
      RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Looking for wall");
    } else {
      RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service");
    }
  }

Hi @sploeger ,

From the following line in your code, I see that you are trying to implement a “non-blocking” version of find_wall service.

The service must be synchronous, meaning, it is a sequential and blocking code. So while the find_wall service is happening, the robot does not do any other motion / task that is not related to find_wall logic.

Also, I need the entire code so I can understand how your WallFollowNode program executes.

The simplest way to fix something that is being repeated / called again is to use a flag and set that to True (or False).
So in pseudo-code, it looks like below:

1. start wall follower
2. call find wall service
   1. if find wall is complete: set flag= True and break out
   2. else, retain flag as False and continue
3. start wall follower logic
4. start other algorithm / logic as required
5. finish task

I hope this helps.

Regards,
Girish

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