Skip to content

No service response when node has both service server and subscriber #101

@anaelle-sw

Description

@anaelle-sw

Hi! I encountered an issue that seems really problematic, but quite strange. When my node's executor has both a subscriber and a service server, the response of the server is never sent.

System:

  • Teensy 3.5
  • Ubuntu 20.04, ROS2 Foxy
  • micro-ROS agent is installed from snap
  • to be sure my micro-ROS Arduino lib was up-to-date, I rebuilt it from the latest version

Steps to reproduce

I have a node quite big, with several service severs, publishers, subscribers. Recently, I moved the add_service_to_executor function after the add_service_to_executor functions in the setup. And this causes my node to not sent anymore the service responses.
So I tried to isolate the problem with this minimal code inspired by the micro-ROS Arduino examples:

#include <micro_ros_arduino.h>

#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <std_srvs/srv/trigger.h>
#include <std_msgs/msg/int32.h>

rcl_subscription_t subscriber;
std_msgs__msg__Int32 msg;

rcl_service_t service;
std_srvs__srv__Trigger_Response res;
std_srvs__srv__Trigger_Request req;

rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;

#define LED_PIN 13
#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){error_loop();}}
#define RCSOFTCHECK(fn) {rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){}}

void error_loop(){
  while(1){
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
    delay(100);
  }
}

void subscription_callback(const void * msgin){  
  const std_msgs__msg__Int32 * msg = (const std_msgs__msg__Int32 *)msgin;
  digitalWrite(LED_PIN, (msg->data == 0) ? LOW : HIGH);  
}

void service_callback(const void * req, void * res){
  std_srvs__srv__Trigger_Request * req_in = (std_srvs__srv__Trigger_Request *) req;
  std_srvs__srv__Trigger_Response * res_in = (std_srvs__srv__Trigger_Response *) res;
  res_in->success = true;
}


void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  
  delay(2000);

  allocator = rcl_get_default_allocator();

  //create init_options
  RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));

  // create node
  RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));

  // create subscriber
  RCCHECK(rclc_subscription_init_default(&subscriber, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), "topic_int"));
    
  // create service
  RCCHECK(rclc_service_init_default(&service, &node,  ROSIDL_GET_SRV_TYPE_SUPPORT(std_srvs, srv, Trigger), "srv_trigger"));

  // create executor
  RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
  RCCHECK(rclc_executor_add_service(&executor, &service, &req, &res, service_callback));    // LINE A
  RCCHECK(rclc_executor_add_subscription(&executor, &subscriber, &msg, &subscription_callback, ON_NEW_DATA));    // LINE B
}

void loop() {
  delay(100);
  RCCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}

This code is uploaded on a Teensy 3.5.
Then I launch a micro-ROS agent (with verbose): micro-ros-agent serial --dev /dev/teensy -v6
And I call the service with CLI: ros2 service call /srv_trigger std_srvs/srv/Trigger '{}'

Issue description

In my complete code, when I invert LINE A and LINE B, the server does receive the request, but no response is sent.

But the "strange" thing is that with this example code, no matter if LINE B is before or after LINE A, the service response won't be sent. Actually, what happens is that immediately after the board reboots (after the upload or hardware reboot), an error happpens when spinning node, and the board is stuck in the error loop.
But when only LINE A or only LINE B is un-commented, everything works as expected.
So my questions are: can someone reproduce this? Why this example code cannot run with both a subscriber and a server?
If I did something wrong when initializing the subscriber or the server in this example, there could be the same errors in my complete code, which may explains the unconsistent behavior depending on the order of the add_X_to_executor functions...

Precisions

  • I tried to configure the subscriber to best effort QoS (rclc_subscription_init_best_effort), the result is the same
  • I cannot explain why the order of lines within my complete code change something, but not within this example. I am working on it and will update this issue if I got something

Thanks a lot for helping!

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions