rosbridge v2 - fragmentation

343 views
Skip to first unread message

fxm...@ipa.fhg.de

unread,
Mar 27, 2013, 11:19:27 AM3/27/13
to rosbrid...@googlegroups.com
Hi all!

We have a non-ros-client that needs to send some huge messages (>200,000 bytes) to ROS.
The non-ros-client only supports tcp-sockets, so I use a self-written tcp2ws wrapper/bridge to connect to rosbridge v2.
This is working well so far (after more testing and fixing some minor issues it can be shared with anyone who is interested..)

Since rosbridge v2 specification draft states that fragmentation and png-compression are in an experimental state, I tried to get it to work but found several problems and have some questions..

I don't think the tcp2ws wrapper is causing the trouble, it's just passing bytes from tcp-sockets to a websockets.. but I might be wrong, so feel free to comment on anything that could be relevant.

1. Is there any version of rosbridge v2 around that has fragmentation support enabled without having to change any code of rosbridge?
Is fragmentation in experimental state (and can be tested / used / ..) or is it in an incomplete and not yet usable state?

2. Is fragmentation meant to be used directly by clients connecting to rosbridge or is it meant to act as a transparent service provided by rosbridge?

When I add the Fragmentation class to capabilities in "rosbridge_protocol.py" and send a message with the op-code "fragmentation", rosbridge starts throwing following error:
fragment: fragment() takes at least 3 arguments (2 given)

After looking through the source code I suspect this is the result of calling a function that can split bigger messages into fragments, basically something similar to what I am doing outside of rosbridge (fragmenting big original message by myself)

Maybe someone could just clarify how fragmentation mechanism is (/will be) designed? ..just to make sure I don't misunderstand the concept behind it..

Also I would like to know if the fragments will be combined by rosbridge and thus not be visible to any other ROS-node?


3. What is the exact format that the fragments should look like?

The specification draft shows following pattern for messages:
{ op: 'fragment', id: <string> , data: <string>, num: <int>, total: <int> }

json.loads(msg) with python cannot decode above line (<string> and <int> filled with correct types), resulting in following error:
Unable to deserialize message from client

For me following example is working, although I'm not sure it is 100% correct.. (means it can be deserialized by rosbridge, fragmentation is not yet working at all)
{"op": "fragment", "id": "1234", "data": "abcdefg", "num": 0, "total": 1}


4. If I got it right, the data-field of a fragment should contain the parts of the string representation of a json-object (e.g. "data": {"bla":"bla"} ).

In case this json-object is not complete, e.g contains only the opening bracket ( { ) without the corresponding closing one or any number of "'s (quotes), deserialization of the message fails.

How am I supposed to split the original string representation JSON-object and fill it into the data-string, if the resulting string cannot be parsed as a correct json-object?

Is there any example of splitting a message into fragments?

Regards,
David Bertram

Russell Toris

unread,
Mar 27, 2013, 2:19:42 PM3/27/13
to rosbrid...@googlegroups.com
Hi David-

Fragmentation is specified in the protocol but no working or developmental version has been submitted at this point. (As a sidenote, you also mentioned PNG compressions: this is indeed implemented and working in the current release).

To answer your other questions, fragmentation is meant to be a concept between the rosbridge server and its client. That is, it should not be visible to ROS nodes. Rosbridge, or its client, will wait for all pieces, put them together, and then pass them along like normal.

You bring up an interesting point with the deserialization that I had not thought about. The thought was that the "data" field would just be a string, and thus not a JSON object itself. Once the strings were combined, it then could be parsed and de-serialized. In the case of the brackets like you mentioned, this entire partial JSON-object should be wrapped as a string (i.e., "data": "{\"bla\":\"bla\"}").

Russell


--
You received this message because you are subscribed to the Google Groups "Rosbridge Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rosbridge-use...@googlegroups.com.
To post to this group, send email to rosbrid...@googlegroups.com.
Visit this group at http://groups.google.com/group/rosbridge-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.





--
Russell Toris
Graduate Student | WPI Department of Computer Science
(203) 984-4571 | rct...@wpi.edu
http://users.wpi.edu/~rctoris/
Message has been deleted

fxm...@ipa.fhg.de

unread,
Mar 28, 2013, 5:09:13 AM3/28/13
to rosbrid...@googlegroups.com
Hi Russel,

thanks for your answer!
Maybe we will try to make use of the PNG compression to shrink our messages..


About the deserialization:
JSON-objects also make use of quotes.. as soon as a quote appears in the data field (no matter if it has outer quotes or not) deserialization fails again... at least what I have seen so far

I will try if it is possible to "double escape" brackets and quotes, so that the final JSON-parser will have a "valid" input string.
If not, we might need some replacement for these things.


David

fxm...@ipa.fhg.de

unread,
Apr 18, 2013, 12:06:00 PM4/18/13
to rosbrid...@googlegroups.com
Am Mittwoch, 27. März 2013 19:19:42 UTC+1 schrieb Russell Toris:
> Hi David-
>
> Fragmentation is specified in the protocol but no working or developmental version has been submitted at this point. (As a sidenote, you also mentioned PNG compressions: this is indeed implemented and working in the current release).
>
>
>
> To answer your other questions, fragmentation is meant to be a concept between the rosbridge server and its client. That is, it should not be visible to ROS nodes. Rosbridge, or its client, will wait for all pieces, put them together, and then pass them along like normal.

I am still trying to fully understand your concept of fragmentation..
Will rosbridge pass fragments to clients or just take incoming fragments?
I guess:
- ..a client can register to rosbridge and set a maximum message size.
If a message is too long, it will be fragmented transparently by rosbridge server and the client will reconstruct the original message from the fragments.
- ..if rosbridge server receives fragmented messages it will reconstruct the original message and publish it to ROS ( maybe fragmented again, for clients that requested that..)


I found code (in fragmentation.py) that will take a message and split it into several fragments, the function name is fragment(), just like the op-code that is defined for fragmented messages..
..now I'm wondering if this is just because of "sub-optimal" naming scheme and the function (to take fragments and rebuild original message) is not yet anywhere in the code.
The other capability-classes just register their functionality with e.g.:
protocol.register_operation("publish", self.publish)

If I try this for fragmentation I think there must be something wrong.. ;)
The spec-draft tells me that if a message has the op-code "fragment" it is already a fragment of a message that has to be buffered (or something alike) by rosbridge and not a message that should be fragmented..
My guess is that the op-code "fragment" should be registered with a functionality that is named "defragment()" or similar.

Yes, I saw this comment:
""" The Fragmentation capability doesn't define any incoming operation
handlers, but provides methods to fragment outgoing messages """
..but following the naming-scheme that is used for the other op-codes I was tempted to look into the function called "fragment()" ;)

Where would (or can) I find the code for "Defragmentation capability"?

Could you estimate when this functionality will start getting developed (/be added to rosbridge)?

We are really interested in getting fragmentation to work, but I am not sure if it is a good idea to try to implement some code that takes care of defragmentation by myself since I am not yet 100% sure about every detail of the underlying concept.
In our use case we want to create message-fragments "manually" (e.g. within matlab) and send them to the rosbridge server.
Thus the server should gather all fragments, reconstruct the original message and publish it..

Yes, it would be nice if fragmenting can be done transparently by rosbridge, but right now we try to keep the rosbridge-client code as "basic" as possible to avoid having to port any client code for whatever platform (programming language, ..) the client is based on.
(btw, that is also the reason why we try to make use of tcp-sockets instead of websockets. I really was wondering why you restrict rosbridge to websockets when the main purpose of rosbridge was to allow as many different "non-ros"-clients to connect to a ros-system.. I might be wrong with this assumption ;) )





..another thought about the JSON-serialization:

> You bring up an interesting point with the deserialization that I had not thought about. The thought was that the "data" field would just be a string, and thus not a JSON object itself. Once the strings were combined, it then could be parsed and de-serialized. In the case of the brackets like you mentioned, this entire partial JSON-object should be wrapped as a string (i.e., "data": "{\"bla\":\"bla\"}").

I am now using json.loads() and json.dumps() to serialize a python-dictionnairy that represents the ROS-message. This is working well so far, albeit it might be possible that an escaped character (if it is the last one of the data-string) could "jump" into the next fragment and the corresponding "\" will stay in the first fragment when the message-fragments get generated...



Regards,
David
Message has been deleted

Chad Jenkins

unread,
Apr 20, 2013, 4:04:21 PM4/20/13
to rosbrid...@googlegroups.com

Hi David,

Thanks for your very thorough message.  It is probably best if Russell or Brandon address this issue.  I know Russell was away last week, so hopefully this issue can be addressed next week.

In general, it does not hurt for you to try implementing fragmenting for rosbridge.  We always welcome contributions to the project help us better realize general purpose interoperability.  This includes contributions of TCP transport (i.e., rosbridge_tcp), Matlab interfaces, etc.  For code contributions, we can move this discussion to the set of rosbridge_suite issues:

  https://github.com/RobotWebTools/rosbridge_suite/issues

Thanks again,
Chad
___



Brandon Alexander

unread,
Apr 20, 2013, 9:56:17 PM4/20/13
to rosbrid...@googlegroups.com
Hi David,

I just filed an issue on GitHub for implementing fragmentation in rosbridge based on your request. When writing the issue, I went through the rosbridge source code and documented the steps for an incoming message inside the issue. I hope you find it easier to understand the inner workings of rosbridge after reading it.

A few things to note:
  1. You are correct that fragmentation support was started a while back. However, it was never finished. The latter steps in the GitHub Issue mention areas in the code for finishing up the implementation.
  2. In regards to coding something up and sending it in, absolutely! We will be happy to review Pull Requests, give any feedback or help if needed, and merge them in. If you would like, fragmentation could be a good start.
  3. Rosbridge is actually a few packages, including rosbridge_library and rosbridge_server. Rosbridge_library handles the JSON to ROS implementation. Rosbridge_server creates the WebSocket server and passes the JSON from the WebSocket to rosbridge_library (and vice versa). We would love TCP support as well. The beauty of rosbridge's architecture is it doesn't need to go through WebSockets at all. Instead of rosbridge_server, there could be a rosbridge_tcp package that goes between TCP and rosbridge_library directly. Check out rosbridge_websocket to get a feel for what's involved in implementing a rosbridge client. We'd also love any Pull Requests related to this feature.
  4. As far as JSON fragmenting is concerned, concatenating all the message fragments then calling JSON.loads should hopefully work okay. An example in Python: json.loads(''.join(json_fragments)).
In short, we highly encourage Pull Request and Issues. Rosbridge is meant to be a project for the community and we are always happy to see participation!

If any questions on the above, please let me know here or as a comment in the GitHub issue.

Best,
Brandon Alexander

fxm...@ipa.fhg.de

unread,
Apr 24, 2013, 10:44:49 AM4/24/13
to rosbrid...@googlegroups.com
Hi,

Chad and Brandon, Thank you for answering and taking the time to write your explanations!
I will look into the code and try to work on those parts.. let's see ;)

Greetings,
David

fxm...@ipa.fhg.de

unread,
Apr 25, 2013, 10:36:50 AM4/25/13
to rosbrid...@googlegroups.com
Hi Brandon,

I looked through your explanations and followed it through the source code..
Your explanations were very helpful to get some insight into the code base.

You mention the following:
"6. Let's assume the OP is "subscribe" since we're discussing fragmentation. Subscriber's subscribe function will be called with the parsed incoming message."

I think this is where we start talking into different directions.
I would have expected something like:
".. the OP is "fragment" since we're discussing fragmentation... "
;-)

I understand that it could be interesting to have rosbridge create fragments from huge messages by itself if a subscriber requests that.
But we (me and my boss ;) ) need just the "opposite". Meaning that we create the fragments manually and have rosbridge taking care of reconstruction and delivery into the ros-system.

So rosbridge would receive message fragments with the op-code "fragment", reconstruct the orginal message after receiving all fragments, and finally treating the reconstructed message just as if it had been sent directly to rosbridge..

We have a "standard" ROS-node subscribing to the topic of those huge messages and we want this node to receive just the original huge message.
For our purpose it should be sufficient if rosbridge can handle incoming fragments and "pass the reconstructed message to the ROS-system".


rosbridge is throwing errors on receiving messages with op-code "fragment".
This op-code should be registered with a function/handler that recombines the fragments and after that rosbridge will pass the reconstructed message to the appropriate OP handler.
I could not (yet) find any class or function that handles this part.

If there is not yet any code for this, I will start implementing a class that can do the following:
- gather fragments
- reconstruct original message
- call appropriate handler for original message (mostly "publish" I guess)


Did I get Fragmentation completely wrong and it's intention was (just) to be able to allow rosbridge clients to define a maximum message length for subscriptions?
After reading the "rosbridge protocol specification.pdf" I expected to use fragmentation just for both "directions"..


Greetings,
David

Brandon Alexander

unread,
May 1, 2013, 1:30:38 PM5/1/13
to rosbrid...@googlegroups.com, fxm...@ipa.fhg.de
Ah, I understand better now your goal and see the source of confusion.

I'll admit the protocol specification and source implementation I described above are a little out of synch, so I'm glad you're bringing this up for discussion.

To clarify we're on the same page, you're suggesting splitting up a rosbridge JSON message into chunks like so:

{ "op": "subscribe", "data": "lots of big data" } => ["{ \"op\":", " \"subscribe\"", ", \"data\"", ...] and sending each chunk to rosbridge, which will then combine the message back to its original and perform the operation?

This seems to match up to what the protocol specification was saying. Would you be putting each fragment inside a message with op: "fragment"? If so, I think it's worth implementing it and sending a pull request in. I am curious though if compressing instead of fragmenting would help in your case?

Also, a heads up, this discussion inspired moving the Rosbridge 2.0 Protocol Specification to GitHub.

Best,
Brandon
Reply all
Reply to author
Forward
0 new messages