Several ROS nodes through a single serial port
Suppose that I have some devices which can be assembled as a chain and which communicate with a single serial port (each device has its own unique id and a proper firmware). These devices can be also very different from each other, both in shapes and functionalities, but share the same hardware (i.e. the same low level API can be used for all of them).
Now you are a forward-looking programmer and you know that what you are developing for a specific purpose will be used for many other projects. You prefer modularity rather than the one-size-fits-all approach. And you also like ROS.
Suppose you develop a base interface to wrap the low level API and implement on top of it the specific device classes. Now, because of the multi-device environment, it is desirable to avoid putting everything inside a single ROS node, in favour of a modular and easily customizable one-node-for-one-device approach (i.e. using ad-hoc launch files for distinct configurations).
Everything is fine.
Everything but the managemant of the serial communication from distinct nodes. Indeed ROS is a multi-process environment and distinct processes do not share resources each other: the file descriptor of the single serial port cannot be shared.
Actually the open()
on the same resource can be called by distinct processes if the exclusive mode is not set (cf. ioctl()
with TIOCEXCL
and TIOCNXCL
options). However, this implies a synchronization mechanism, and again, sharing something among processes.
- How would you face this problem?
- Are there any workaround in ROS which I do not know?
- How much overhead w.r.t. to a single I/O operation would produce a communication handler "super-node" (e.g. with
read()
,write()
,...
ROS services)?
Have you considered using plugins? The 'single node' could simply be in charge of managing your contended resource (ie: the serial port), and the plugins (nodelets?) could handle the actual traffic.
I've phrased what you are describing the facade (or service abstraction) versus the transparant bridge problem: a bridging approach will typically import domain concepts from 'beyond' the bridge into your ROS nodegraph, the facade completely hides everything behind a ROS API (svcs, topics).
This is not necessarily true (the multiprocess part): it just happens that most nodes get mapped onto processes (at deployment time, or by design), but they don't have to be (nodelets again).
Thank you for helping me once again! I was just reading about
nodelets
which I have never used before. It seems to do the trick, but I have to dig a bit more the get the whole picture.Well nodelets won't avoid importing domain concepts from beyond the bridge into your ROS application (ie: node graph), but they will minimise potential communication overhead, while still supporting the distributed development that normal nodes allow.
Note that my initial comment (about plugins) is not tied to using nodelets. I merely meant that the plugins could 'behave' like nodelets.
Why should I use something which behave like
nodelets
instead of usingnodelets
itself? I mean, start from scratch takes time and probably leads to a similar result. Are there any particular reasons to prefer this way (apart the perfect fitting to my problems, if well designed)?And - if I understand correctly - if I decide to switch to plugin approach, I'll use it "forever". Could this be a problem in some circumstances? Sorry if I'm boring you, but it's a remarkable restyle and I just want to be sure that it won't be useless.
As I wrote earlier: nodelets are essentially nodes, but mapped on threads, so with a shared address space, making passing of pointers possible. That avoids communication overhead (but the advantages wrt jitter are probably more significant).
But, you still need to guard / expose your contended ..
.. resource, so you'll probably create a nodelet that offers those
read()
,write()
,...
services you mentioned. Result: you have a transparent bridge and all your ROS nodes now need to 'know' how to deal with domain concepts (ie: interpreting serial traffic). Personally I'm not sure that .... is a good thing.
The service proxy / facade pattern would basically 'hide' the entities behind the bridge, while exposing a ROS API that still allows interested ROS participants to interact with the components beyond the bridge. This style avoids leaking knowledge / implementation details.
Less knowledge / assumptions is always (I posit) a good thing in software components, as it increases their reusability.
Note that this issue is not limited to serial ports: the same issues come up with briding into fieldbus networks fi. It's also not a dilemma: hybrids are possible.
I know that I've been a bit slow on the uptake, but I got it. Thank you very much, you are great!
No problem.
Btw: I feel these kind of things are more suited for a discussion, as there probably isn't one specific answer that is the answer.
discourse.ros.org
is good for discussions. ROS Answers is for straightforward Q&A style things.Hello.
I am facing a similar problem on a project. I need do communicate with some embedded board on a 485 bus. I tried with rosserial, but that individual use of the port and the multitask approach of rosserial_node is very trick for me.
Did you have any success on what you were developing?