3

I'm trying to setup a ROS Action server & client to handle sending images (encoded as 64-bit strings) between Python and ROS (with the goal of making the image something other scripts can pull from ROS). Being very new to all of this (Python, Ubuntu, Bash, ROS, etc...), I'm having a very difficult time determining HOW exactly to do this. I think part of the reason is that the ROS wiki tutorials/documentation are linear to a fault, and the process just comes across as convoluted and extraordinarily complicated. Does anyone out there know of any non-ROS-wiki related/dependent tutorials to help me figure this out? Or can you create a concise step-by-step guide to establishing this system? I've been unable to find much of anything relating to this topic specifically - which makes me think it's either a very uncommon use, or it's super easy and I'm just not at that level yet.

My attempt at a solution is essentially just getting the information flow down. I want Python to be able to read in an image, convert it to bytes (using b64encode), and send it over to ROS to publish as an action. (Thus, a stream of images can be sent with no pause, as would be done with a service, if I understand correctly.) Anything subscribed to the node (or server, however that works, I'll figure it out when I get there) can then see the images and pull them from the action server.

Now, I'm being told an action is the best way to do this. Personally, I don't see why a service wouldn't suffice (and I've at least gotten one of those to work).

Thanks again for any help you all can provide!

Edit: The end application here is for video streaming. A server will grab live video, convert it to images, change those to byte strings, and stream them to the client, which will then publish them to a ROS Action Server.

godfreap
  • 333
  • 1
  • 5
  • 13
  • Can you elaborate a bit more what exactly you want to achieve? As far as I understand it, the Python node shall just wait for an "image request" and when such a request comes, load the image and send it to the requester (i.e. the Python node is not doing any heavy work that needs some time to get finished). If this is correct, I think a simple service is totally sufficient and much less painful to implement. – luator Sep 30 '15 at 17:00
  • The problem with services is, that the requester is blocked until the request is finished. With actions, the requester is not blocked but subscribes a callback which will receive the result once the request is finished (and the request can also be aborted in the meantime and progress feedback can be sent). Actions are therefore useful for requests that need longer to terminate but on the other hand they are much more complicated to implement (see also [here](http://answers.ros.org/question/11834/when-should-i-use-topics-vs-services-vs-actionlib-actions-vs-dynamic_reconfigure/)). – luator Sep 30 '15 at 17:06
  • ...So if you don't need this features, I would better go for the service. – luator Sep 30 '15 at 17:06
  • Regarding your edit: Do you need **all** (or mostly all) images of that video stream? If yes, a *topic* would be best (simply broadcasts the messages without being requested and other nodes can subscribe to the stream with callbacks). If you need only **few** images and only in specific situations, I still think services are best. Maybe I miss something in your task but I don't see a good reason to take the trouble of implementing an action server for such a simple task. Of course, if you boss wants so, you should probably also look into it. Unfortunately I also don't know of a better tutorial – luator Sep 30 '15 at 17:17
  • Rereading your question, I'm not absolutely sure what you mean by "*which will then publish them to a ROS Action Server.*" Do you mean "Some node A reads the stream and publishs all images via topic to node B (which is the action server) and then another node C requests single images from B"? – luator Sep 30 '15 at 17:23
  • I would say I need all of them. And that was my first idea: subscribe to the relevant topic and just endlessly flow the images with a delimiter to separate the images. I already have 90% of that written, too. We'll eventually be requesting frames of a video, but I don't think that changes anything, since they should all be sequential. I think the main reason we need at least services is to make them accessible to other programs. Though it seems trivial to include the subscriber in an analysis script, the images should be available across the system to any running script that can access ROS. – godfreap Sep 30 '15 at 17:23
  • Regarding your last comment, yes, I believe that's right. I have a very shaky grasp on the whole heirarchy, so I'm not entirely sure how action/service servers are related to nodes, clients, and topics... – godfreap Sep 30 '15 at 17:24
  • Note, that topics are no endless streams in the traditional sense, but you can only publish self-contained messages, i.e. no need for delimiters (btw, there is already a [message type for images](http://docs.ros.org/api/sensor_msgs/html/msg/Image.html)). In general any ROS node (=script/program that is connected to ROS) that can access a *service* can also subscribe to *topics*. It's more a question which type of access is better suited for the specific task the node is doing. Servers are nodes themselves that just happen to advertice a service to other (client-)nodes. – luator Sep 30 '15 at 17:46
  • I've actually been using `from sensor_msgs.msg import Image` in my ROS publisher. Messing around with transferring via topics, I see the delimiter, but then is there a difference in which is faster - services or topics? is one more suited for streaming? And by the way, thanks @luator , you've been super helpful since I joined the site :D – godfreap Sep 30 '15 at 17:56
  • You're welcome, I am happy if I can help :) I would say topics are faster, especially if there are multiple subscribers. The publisher just publishes the images and all subscribers automatically receive them via callbacks (and without copy due to shared memory). In contrast with services, each client has to actively request every single image which increases communication overhead and clients may miss single images. On the other hand, this avoids unnecessary communication when the client needs not all images only single ones in specific situations (i.e. they only request, if they need it). – luator Sep 30 '15 at 18:10
  • So it really depends on what the client/subscriber needs. If it needs every new image that is published, use a topic. If it needs only single images and only in certain situations, use a service. – luator Sep 30 '15 at 18:12
  • I'm glad I was at least right in thinking that topics are easiest and now they appear to be fastest too. I did a short test and based on the average time to transmit 12 images in byte strings, I can do 1,787 frames per second. I suspect that would be fast enough! haha. Thanks again @luator, I'm going to talk to my boss about this and see if he still thinks services are best. You clarified a lot of this for me! Thanks a lot! :D – godfreap Sep 30 '15 at 18:20

1 Answers1

0

I think you're overcomplicating it. I wouldn't implement it as an actionlib server, although that is one approach. I've created a few similar systems, and this is how I structured them:

  1. Write your node that streams video by publishing images on a topic. You can implement this as an actionlib server, but that's not required. In my case, I used the pre-existing raspicam_node to read a Raspberry Pi's camera. If you want to implement this in Python, read the tutorial on creating a publisher.
  2. Create a node that subscribes to your image topic, and then reads the image from the topic message. Again, the tutorial shows how to create a subscriber. The main difference is that you'd use either CompressedImage or Image from sensor_msgs.msg as your message type.

For the subscriber-side, here's an example Python ROS node I wrote that implements a MJPEG streamer. It subscribes to a topic, reads the image data, and re-publishes it via a streaming HTTP response. Even though it's "slow Python", I get less than 1 second of latency.

Cerin
  • 60,957
  • 96
  • 316
  • 522