Generic adapter for TCP / UDP / serial communications?
I am writing driver nodes that control various sensors attached to my CPU. For instance, NMEA messages come from a GPS-enabled device over UDP, while temperature readings are reported over serial.
I could write the thermometer driver node to specifically listen for messages over serial, but this seems like a separation-of-concerns violation.
Instead I think I'd rather have a generic serial driver, and a generic UDP driver, and a generic TCP driver, which all publish a generic line message type, then my thermometer driver could be configured to subscribe to the appropriate topic where these lines are coming in, without caring what communication method is being used upstream.
Is there an existing standard package that would offer this? It's not hard to write myself of course, but I'd like to not reinvent the wheel.
(To emphasize one point, this isn't about sending serialized ROS messages over serial or UDP or whatever.)
Asked by rgov on 2020-04-03 14:24:55 UTC
Answers
For ROS 1 I believe there are a few packages that go in this direction, but nothing I could really point you to as being "standard".
For ROS 2 (but you tagged this melodic
, so that may not really help you), there is ros-drivers/transport_drivers. Note: these are more libraries than ROS nodes, but it's not entirely clear from your question text whether that would be a problem.
And for NMEA devices specifically, you could look at ros-drivers/nmea_comms.
Asked by gvdhoorn on 2020-04-04 04:56:56 UTC
Comments
Hi
What we have done is to create a serial node and publish to a string topic. We have done the same for a tcp and udp node as well.
For serial node you have to decide is you want to publish from a read or publish on a terminator. For ASCII protocols its usually done by ending with a terminator. So your serial node should be of type ASCII or BINARY. For ASCII it would send on a parameterized terminator. For BINARY it would send whatever the read returns. It would be the responsibility of the high node receiving the BINARY data to assemble the data into a packet.
BTW you will have to you assign to move the data from the serial port to the string topic.
Hope all that helps.
Separating in serial into a string topic also makes testing, and debugging easier. An extra feature is that if you have the same type of device, like a GNSS/GPS, that returns apacket of UDP instead of serial your GNSS/GPS node does not have to change. We actually ran into this situation and all that was required was to change a launch file.
Asked by borgcons on 2020-06-08 16:08:58 UTC
Comments
Months ago I stumbled upon this thread when I searched for a ethernet bridging node. As I have not been able to find any suitable one, I have created one: https://github.com/UniBwTAS/ethernet_bridge
Perhaps you (or anyone coming across this thread from Google) can also benefit from it. However, it does not come with serial communication nodes.
Asked by pberthold on 2021-07-20 12:31:10 UTC
Comments
At least for serial there have been some, and the velodyne_driver package follows a similar design pattern (ie: dedicated nodelet handles network traffic and (initial) deserialisation, other nodelet(s) convert to ROS msgs).
I'm not aware of anything that would be a standard "goto implementation" you could reuse (but that doesn't mean there aren't any of course).
Three reasons why I believe node authors often decide to not separate these concerns:
asio
for C++ orpyserial
for Python, it takes only a few lines of code to get something to workFinally: network and serial ports are ..
Asked by gvdhoorn on 2020-04-04 04:49:19 UTC
.. typically not examples of shared resources, and require specific interaction patterns to function correctly. Both at the level of the transport, and at the level of communication with whatever is "on the other side".
While that does seem like a responsibility/concern which could be nicely separated -- and some packages that bridge systems like CAN(open)/Ethercat/etc do just that -- it also has a tendency to couple nodes (ie: the bridge and the nodes talking to the bridge), as now two nodes need to work together to maintain proper ordering of messages (fi). This is especially true if the transport/comms channel being wrapped/bridged has no or a different concept of addressing, or doesn't support asynchronous messaging.
Note: I'm not saying your idea is not a good one. I just wanted to discuss it a bit.
That's also why this is not an answer.
I believe the reuse in these cases typically happens at the "library for serial port/network access"-level, instead of the ROS node level.
Asked by gvdhoorn on 2020-04-04 04:53:53 UTC