0
$\begingroup$

Rosanswers logo

I am running ROS (Kinetic on Ubuntu 16.04) on two machines (desktop pc and Jackal pc) and the Jackal pc is set as the ROS Master. The both machines are connected over a wireless network. I am writing a python node which is supposed to run on my machine and in case of being disconnected from the wifi to perform some action. To keep it simple for now, this action can be just a ROS warning. So my question is:

What is the best way in ROS to check/detect in the node code if the connection is down (i.e. my machine has disconnected from the network)?

When the connection goes down, the nodes that are run on my machine (in sourced terminals) are waiting for the master which is on the Jackal to be reconnected so that the publishers can continue to publish the messages. In this case when the connection is down if I run rostopic list in a sourced terminal there is no output at all. The same goes for any rosrun/roslaunch commands.
I am sure that there is also a way to check if there is a connection to the ROS Master but I could not find a working solution. I can always write my own timeout method but I would like to know if an proper way to do this already exists.


Originally posted by pavel92 on ROS Answers with karma: 1655 on 2018-08-21

Post score: 2


Original comments

Comment by PeteBlackerThe3rd on 2018-08-21:
If this definitely isn't a 'proper' method but you could use a system call to ifconfig <NIC_name> to find out if your wi-fi connection is down very quickly.

Comment by gvdhoorn on 2018-08-22:
An alternative to checking (but something that might actually be better): a multimaster setup.

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

Seems like ros::master::check () would be one way to go.

API

techno74 asking and answering a similar question.

A similar function for python is mentioned in the previous question.

rosgraph.is_master_online()


Originally posted by Reamees with karma: 591 on 2018-08-22

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by pavel92 on 2018-08-22:
I tried the rosgraph.is_master_online() and it works without a problem when there is a network connection. The problem still occurs when the network goes down as the node is in limbo state. In this case rosgraph blocks the node and fails to check for the master

Comment by Ariel_GLR on 2019-04-11:
having same issue as pavel92, every method which somehow relies on rosgraph, somehow blocks. it s as though resorption until reconnecting

Comment by aa-tom on 2021-10-20:
I'm also facing this issue. I've raised a PR with rosgraph here adding an optional timeout parameter to rosgraph.is_master_online(). In the meantime, the following solution seems to be sufficient, despite feeling a little hacky

import socket
...
socket.setdefaulttimeout(timeout)
rosgraph.is_master_online()
socket.setdefaulttimeout(None)
...

Comment by gvdhoorn on 2021-10-21:
@aa-tom: might be nicer to do:

old_def_timeout = socket.getdefaulttimeout()
socket.setdefaulttimeout(timeout)
rosgraph.is_master_online()
socket.setdefaulttimeout(old_def_timeout)

that would future-proof it a little more (if it ever changes).

Comment by max11gen on 2022-03-07:
Is there anything like this for ROS2 as well? I mean obviously you can't check if the remote master is online, because there is no master. But can I check if another machine is online or if a specific node is running on the network?

$\endgroup$
0
$\begingroup$

Rosanswers logo

I would also like to add my input on this matter! The above solution is working fine and its native to ROS, however it stopped working for me when I started using Gstreamer to get a UDP webcam stream off of a RPI.

A bit more about the setup:

  • ROS Noetic on Linux 20.04

  • Static Network 10.0.0.x/24 ( 255.255.255.0 )

  • Laptop ( master ) address 10.0.0.1

                              Laptop (ROS master) <---- ethernet -----> RPI <--- USB camera 
        UDP stream receivever <-/                                        \-> UDP stream sender
    

using rosgraph.is_master_online() would detect the connection, however when the ethernet cable was disconnected, everything ROS related on the RPI side would halt.

What solved that issue, was an approach that slightly deviated from the pure ROS methods. I created a function following this tutorial that would check if there is a connection with the master:

 def ping_master(self):
    # try to ping the master IP
    try:
        socket.setdefaulttimeout(1)
        # if we do not receive data for 1 second except will kick in

        soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # AF_INET: address family
        # SOCK_STREAM: type for TCP

        host = "10.0.0.1"
        port = 11311

        server_address = (host, port)
        soc.connect(server_address)

    except OSError as error:
        return False
        # function returns false value
        # disconnection is detected

    else:
        soc.close()
        # closing the connection after the
        # communication with the master is complete
        return True

Do not forget to change the host and port based on your network setup!

And call it in the main loop like so:

while not rospy.is_shutdown():
    try:
        mainRate.sleep()
    except rospy.ROSInterruptException:  # shutdown
        break


    if self.ping_master():
        
        print("{}: {} - Ros Master Is Online".format(time.strftime("%d.%m.%Y-%H:%M:%S"),self.node_name))
        # do stuff here when master is online 
            
    else:

        print("{}: {} - Ros Master Went Offine".format(time.strftime("%d.%m.%Y-%H:%M:%S"),self.node_name))
        # do stuff here when master is offline 


    rospy.on_shutdown(self.on_shutdown_cb)

Hope this helps someone in the future!


Originally posted by ekptwtos with karma: 35 on 2022-08-18

This answer was NOT ACCEPTED on the original site

Post score: 1

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.