-
Notifications
You must be signed in to change notification settings - Fork 135
Description
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!