def __init__(self, monitor_port=11611, domain=''): '''.......................................................................... Initialize method of the local master. @param monitor_port: The port of the RPC Server, used to get more information about the ROS master. @type monitor_port: int ..........................................................................''' if rospy.has_param('~rosmaster_hz'): Discoverer.ROSMASTER_HZ = rospy.get_param('~rosmaster_hz') self.master_monitor = MasterMonitor(monitor_port) name = self.master_monitor.getMastername() # create the txtArray for the zeroconf service of the ROS master materuri = self.master_monitor.getMasteruri() # test the host for local entry masterhost, masterport = MasterInfo.MasteruriToAddr(materuri) if (masterhost in ['localhost', '127.0.0.1']): sys.exit("'%s' is not reachable for other systems. Change the ROS_MASTER_URI!", masterhost) rpcuri = ''.join(['http://', socket.gethostname(), ':', str(monitor_port), '/']) txtArray = ["timestamp=%s"%str(0), "master_uri=%s"%materuri, "zname=%s"%rospy.get_name(), "rpcuri=%s"%rpcuri] # the Zeroconf class, which contains the QMainLoop to receive the signals from avahi Zeroconf.__init__(self, name, '_ros-master._tcp', masterhost, masterport, domain, txtArray) # the list with all ROS master neighbors with theirs SyncThread's and all Polling threads self.masters = MasterList(self.masterInfo, self.requestResolve, self.checkLocalMaster) # set the callback to finish all running threads rospy.on_shutdown(self.finish)
def getDefaultRPCPort(zeroconf=False): try: masteruri = MasterMonitor._masteruri_from_ros() rospy.loginfo("ROS Master URI: %s", masteruri) from urlparse import urlparse return urlparse(masteruri).port+(600 if zeroconf else 300) except: import traceback print traceback.format_exc() return 11911 if zeroconf else 11611
class Discoverer(Zeroconf): ''' This class is a subclass of Zeroconf to handle the callback of the avahi daemon. Furthermore the informations of the local ROS master will be stored and a method to check the state of the local ROS master and update it in avahi if needed. A list with all remote ROS masters is managed by MasterList. ''' ROSMASTER_HZ = 2 # the test rate of ROS master state in hz def __init__(self, monitor_port=11611, domain=''): '''.......................................................................... Initialize method of the local master. @param monitor_port: The port of the RPC Server, used to get more information about the ROS master. @type monitor_port: int ..........................................................................''' if rospy.has_param('~rosmaster_hz'): Discoverer.ROSMASTER_HZ = rospy.get_param('~rosmaster_hz') self.master_monitor = MasterMonitor(monitor_port) name = self.master_monitor.getMastername() # create the txtArray for the zeroconf service of the ROS master materuri = self.master_monitor.getMasteruri() # test the host for local entry masterhost, masterport = MasterInfo.MasteruriToAddr(materuri) if (masterhost in ['localhost', '127.0.0.1']): sys.exit("'%s' is not reachable for other systems. Change the ROS_MASTER_URI!", masterhost) rpcuri = ''.join(['http://', socket.gethostname(), ':', str(monitor_port), '/']) txtArray = ["timestamp=%s"%str(0), "master_uri=%s"%materuri, "zname=%s"%rospy.get_name(), "rpcuri=%s"%rpcuri] # the Zeroconf class, which contains the QMainLoop to receive the signals from avahi Zeroconf.__init__(self, name, '_ros-master._tcp', masterhost, masterport, domain, txtArray) # the list with all ROS master neighbors with theirs SyncThread's and all Polling threads self.masters = MasterList(self.masterInfo, self.requestResolve, self.checkLocalMaster) # set the callback to finish all running threads rospy.on_shutdown(self.finish) # #start the signal main loop # if (not rospy.is_shutdown()): # self.start() @property def getName(self): return self.masterInfo.name def finish(self, *args): '''.......................................................................... Removes all remote masters and unregister their topics and services. Stops the QMainLoop of avahi. ..........................................................................''' rospy.logdebug("Stop zeroconf DBusGMainLoop") if hasattr(self.master_monitor, 'rpcServer'): self.master_monitor.rpcServer.shutdown() self.stop() self.masters.removeAll() def __repr__(self): '''.......................................................................... String representation of local ros manager ..........................................................................''' return ''.join(['Discoverer: ', repr(self.masterInfo)]) def on_server_running(self): rospy.loginfo("Zeroconf server now running.") def on_server_collision(self): rospy.logfatal("Zeroconf server collision.") self.collision = True self.finish() rospy.signal_shutdown("Zeroconf server collision.") def on_server_failure(self): rospy.logfatal("Zeroconf server error.") self.finish() rospy.signal_shutdown("on_server_failure") def on_group_established(self): rospy.logdebug("Service %s established.", self.masterInfo.name) def on_group_collision(self): if not self.isStopped(): rospy.logwarn("ERROR: Service name collision. %s already exists. Retry in 3 sec...", self.masterInfo.name) self._removeService() time.sleep(3) self._registerService() def on_group_failure(self, error): rospy.logfatal("Error in group %s: %s", self.masterInfo.name, error) self.finish() rospy.signal_shutdown("Error in group") def on_group_removed(self, name): if (name != self.masterInfo.name): rospy.loginfo("%s group removed from zeroconf.", name) self.masters.removeMaster(name) def on_resolve_reply(self, master_info): rospy.logdebug("on_resolve_reply: %s", master_info.name) self.masters.updateMaster(master_info) def on_service_updated(self): self.masters.updateMaster(self.masterInfo) def on_resolve_error(self): self.masters.checkMastersState() def checkLocalMaster(self, master_info): '''.......................................................................... Compares the current state of the local ROS master. If the state was changed the avahi sevice will be updated @param master_info: will not be used, is only for compatibility to the Polling class. ..........................................................................''' # get the state of the local ROS master try: # compare the current system state of ROS master with stored one and update the timestamp if needed if self.master_monitor.checkState(): # sets a new timestamp in zeroconf # rospy.logdebug("state of local master changed") rpcuri = self.masterInfo.getTXTValue('rpcuri', '') masteruri = self.masterInfo.getTXTValue('master_uri', '') self.masterInfo.txt = ["timestamp=%s"%str(self.master_monitor.getCurrentState().timestamp), "master_uri=%s"%masteruri, "zname=%s"%rospy.get_name(), "rpcuri=%s"%rpcuri] self.updateService(self.masterInfo.txt) return self.masterInfo except: import traceback rospy.logerr("Error while check local master: %s", traceback.format_exc()) return None