ros-drivers / rosserial

A ROS client library for small, embedded devices, such as Arduino. See: http://wiki.ros.org/rosserial
517 stars 525 forks source link

subscriber callback function taking too long will affect pubisher? #437

Closed hyansuper closed 5 years ago

hyansuper commented 5 years ago

I am using a esp8266 board and the arduino IDE and rosserial, communication through wifi.

In the end of subscriber callback function, I make publisher to publish a return code to indicate the end of callback execution. I know that best practise is not doing long execution in the callback, but since it's not easy to implement multithread in arduino, so I just write the long time execution in callback (about 5 seconds). If the callback takes to long, the publish function will not actually publish anything, may I know what really cause the problem?

#include <ESP8266WiFi.h>
#include <ros.h>
#include <std_msgs/Int16.h>

const char* ssid     = "********";
const char* password = "***********";
IPAddress server(192,168,0,90);
const int16_t serverPort = 11411;
ros::NodeHandle nh;
std_msgs::Int16 ret_msg;
ros::Publisher pub("ret_code", &ret_msg);

void messageCb(const std_msgs::Int16& msg){
  delay(msg.data);//to simulate long time execution
  ret_msg.data++;
  pub.publish(&ret_msg);
}

ros::Subscriber<std_msgs::Int16> sub("cmd", &messageCb );

void setup(){
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  // Set the connection to rosserial socket server
  nh.getHardware()->setConnection(server, serverPort);
  nh.initNode();
  nh.advertise(pub);
  nh.subscribe(sub);
}
void loop(){
  nh.spinOnce();
  delay(10);
}
romainreignier commented 5 years ago

The nh.spinOnce() should be called regularly otherwise a timeout will occur. You may try ti increase the timeouts but it does not seem like a great idea. Also, note that is you try to call nh.spinOnce() from within a callback, you could get some issue because other callbacks may be called while already in a callback. If there is no mean to refactor your code to return to the loop() fast enough, maybe it is time to upgrade to a faster processor (did you see the Teensy 4.0 @ 600 MHz 😍).

hyansuper commented 5 years ago

Thanks for your answer. Faster processor won't help in my case. my callback has to be run in a predefined period. I am actually trying to minic the behavior of ROS actions, but actions aren't supported in rosserial. Do you mean nh.spinOnce() should be call frequently to ensure connection? If so, I can put some nh.spinOnce() in callback when I am sure no other callback will occur.

romainreignier commented 5 years ago

I am actually trying to minic the behavior of ROS actions, but actions aren't supported in rosserial.

In our Qt version of rosserial_client, we have a simple action client implementation : action_client.h

Do you mean nh.spinOnce() should be call frequently to ensure connection?

Yes, exactly.

If so, I can put some nh.spinOnce() in callback when I am sure no other callback will occur.

Has I told you, it is a bad idea.

hyansuper commented 5 years ago

rosserial_qt seems promising, but I am talking about simple controllers like Arduino or Esp32/Esp8266, which dosen't run on OS.

romainreignier commented 5 years ago

rosserial_qt seems promising, but I am talking about simple controllers like Arduino or Esp32/Esp8266, which dosen't run on OS.

Yes, sure, but it was to show you an example of action client implementation.