'ROS - How do I publish a message and get the subscribed callback immediately

I have a ROS node that allows you to "publish" a data structure to it, to which it responds by publishing an output. The timestamp of what I published and what it publishes is matched.

Is there a mechanism for a blocking function where I send/publish and output, and it waits until I receive an output?

ros


Solution 1:[1]

I think you need the ROS_Services (client/server) pattern instead of the publisher/subscriber.


Here is a simple example to do that in Python:

Client code snippet:

import rospy
from test_service.srv import MySrvFile

rospy.wait_for_service('a_topic')
try:
    send_hi = rospy.ServiceProxy('a_topic', MySrvFile)
    print('Client: Hi, do you hear me?')
    resp = send_hi('Hi, do you hear me?')
    print("Server: {}".format(resp.response))

except rospy.ServiceException, e:
    print("Service call failed: %s"%e)

Server code snippet:

import rospy
from test_service.srv import MySrvFile, MySrvFileResponse

def callback_function(req):
    print(req)
    return MySrvFileResponse('Hello client, your message received.')

rospy.init_node('server')
rospy.Service('a_topic', MySrvFile, callback_function)
rospy.spin()

MySrvFile.srv

string request
---
string response

Server out:

request: "Hi, do you hear me?"

Client out:

Client: Hi, do you hear me?
Server: Hello client, your message received.

Learn more in ros-wiki


[UPDATE]

  • If you are looking for fast communication, TCP-ROS communication is not your purpose because it is slower than a broker-less communicator like ZeroMQ (it has low latency and high throughput):
  1. ROS-Service pattern equivalent in ZeroMQ is REQ/REP (client/server)
  2. ROS publisher/subscriber pattern equivalent in ZeroMQ is PUB/SUB
  3. ROS publisher/subscriber with waitformessage equivalent in ZeroMQ is PUSH/PULL

ZeroMQ is available in both Python and C++

  • Also, to transfer huge amounts of data (e.g. pointcloud), there is a mechanism in ROS called nodelet which is supported only in C++. This communication is based on shared memory on a machine instead of TCP-ROS socket.

    What exactly is a nodelet?

Solution 2:[2]

Since you want to stick with publish/ subscribers, assuming from your comment, that services are to slow I would have a look at waitForMessage (Documentation).

And for an example on how to use it you can have a look at this ros answers question.

All you need to do is to publish your data and immediately call waitForMessage on the output topic and manually pass the received message to your "callback".

I hope this is what you were looking for.

Solution 3:[3]

To get this request/reply behaviour ROS has a mechanism called ROS service.

You can specify the input and output of your service in a service file similar to a ROS message definition. You can then call the service of a node with your input and the call will receive an output when the service is finished.

Here is a tutorial how to use this mechanism in python. If you prefer C++ there is also one, you should find it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 LeoE
Solution 3 Malefitz