def updateMaster(self, master):
   '''
   Updates the information of the ros master. If the ROS master not exists, it 
   will be added.
   
   @param master: the ROS master to update
   @type master: L{master_discovery_fkie.msg.ROSMaster}
   '''
   # remove master, if his name was changed but not the ROS master URI
   root = self.invisibleRootItem()
   for i in reversed(range(root.rowCount())):
     masterItem = root.child(i)
     if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
       root.removeRow(i)
       break
   
   # update or add a the item
   root = self.invisibleRootItem()
   doAddItem = True
   for i in range(root.rowCount()):
     masterItem = root.child(i)
     if (masterItem == master.name):
       # update item
       masterItem.master = master
       masterItem.updateMasterView(root)
       doAddItem = False
       break
     elif (masterItem > master.name):
       root.insertRow(i, MasterItem.getItemList(master, (nm.is_local(nm.nameres().getHostname(master.uri)))))
       doAddItem = False
       break
   if doAddItem:
     root.appendRow(MasterItem.getItemList(master, (nm.is_local(nm.nameres().getHostname(master.uri)))))
 def hostNameFrom(cls, masteruri, address):
   '''
   Returns the name generated from masteruri and address
   @param masteruri: URI of the ROS master assigned to the host
   @type masteruri: C{str}
   @param address: the address of the host
   @type address: C{str}
   '''
   name = nm.nameres().mastername(masteruri, address)
   if not name:
     name = address
   return '@'.join([name, nm.nameres().hostname(address)])
 def run(self):
   index = 0
   while (not rospy.is_shutdown()) and self._running:
     msg = None
     address = None
     status_text = ''.join(['listen on network: ', str(index), ' (', str(self._networks_count), ')'])
     self.status_text_signal.emit(status_text)
     with self.mutex:
       while True:
         try:
           (msg, address) = self.sockets[index].recvfrom(1024)
           hostname = None
           force_update = False
           if not address is None:
             try:
               hostname = self._hosts[address[0]]
             except:
               hostname = nm.nameres().hostname(str(address[0]))
               if hostname is None or hostname == str(address[0]):
                 self.status_text_signal.emit(''.join(['resolve: ', str(address[0])]))
                 try:
                   (hostname, aliaslist, ipaddrlist) = socket.gethostbyaddr(str(address[0]))
                   nm.nameres().addInfo(None, hostname, hostname)
                   nm.nameres().addInfo(None, address[0], hostname)
                 except:
                   import traceback
                   print traceback.format_exc()
                   pass
               self._hosts[address[0]] = hostname
           if not msg is None:
             try:
               (version, msg_tuple) = Discoverer.msg2masterState(msg, address)
               if not self._discovered.has_key(index):
                 self._discovered[index] = dict()
                 force_update = True
               self._discovered[index][address] = (hostname, time.time())
             except Exception, e:
               import traceback
               print traceback.format_exc()
               pass
           if force_update:
             self._updateDisplay()
         except socket.timeout:
   #        rospy.logwarn("TIMOUT ignored")
           break
         except socket.error:
           import traceback
           rospy.logwarn("socket error: %s", traceback.format_exc())
           break
         except:
예제 #4
0
    def updateMaster(self, master):
        '''
    Updates the information of the ros master. If the ROS master not exists, it 
    will be added.
    
    @param master: the ROS master to update
    @type master: L{master_discovery_fkie.msg.ROSMaster}
    '''
        # remove master, if his name was changed but not the ROS master URI
        root = self.invisibleRootItem()
        for i in reversed(range(root.rowCount())):
            masterItem = root.child(i)
            if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
                root.removeRow(i)
                try:
                    del self.pyqt_workaround[masterItem.master.name]
                except:
                    pass
                break

        # update or add a the item
        root = self.invisibleRootItem()
        doAddItem = True
        for i in range(root.rowCount()):
            masterItem = root.child(i, self.COL_NAME)
            if (masterItem == master.name):
                # update item
                masterItem.master = master
                masterItem.updateMasterView(root)
                doAddItem = False
                break
            elif (masterItem > master.name):
                mitem = MasterItem.getItemList(
                    master,
                    (nm.is_local(nm.nameres().getHostname(master.uri))))
                self.pyqt_workaround[
                    master.
                    name] = mitem  # workaround for using with PyQt: store the python object to keep the defined attributes in the MasterItem subclass
                root.insertRow(i, mitem)
                mitem[self.COL_NAME].parent_item = root
                doAddItem = False
                break
        if doAddItem:
            mitem = MasterItem.getItemList(
                master, (nm.is_local(nm.nameres().getHostname(master.uri))))
            self.pyqt_workaround[
                master.
                name] = mitem  # workaround for using with PyQt: store the python object to keep the defined attributes in the MasterItem subclass
            root.appendRow(mitem)
            mitem[self.COL_NAME].parent_item = root
 def run(self):
   index = 0
   while (not rospy.is_shutdown()) and self._running:
     msg = None
     address = None
     status_text = ''.join(['listen on network: ', str(index), ' (', str(self._networks_count), ')'])
     self.status_text_signal.emit(status_text)
     with self.mutex:
       while True:
         try:
           (msg, address) = self.sockets[index].recvfrom(1024)
           hostname = None
           force_update = False
           if not address is None:
             try:
               hostname = self._hosts[address[0]]
             except:
               hostname = nm.nameres().hostname(str(address[0]))
               if hostname is None or hostname == str(address[0]):
                 self.status_text_signal.emit(''.join(['resolve: ', str(address[0])]))
                 try:
                   (hostname, aliaslist, ipaddrlist) = socket.gethostbyaddr(str(address[0]))
                   nm.nameres().addInfo(None, hostname, hostname)
                   nm.nameres().addInfo(None, address[0], hostname)
                 except:
                   import traceback
                   print traceback.format_exc()
                   pass
               self._hosts[address[0]] = hostname
           if not msg is None:
             try:
               (version, msg_tuple) = Discoverer.msg2masterState(msg, address)
               if not self._discovered.has_key(index):
                 self._discovered[index] = dict()
                 force_update = True
               self._discovered[index][address] = (hostname, time.time())
             except Exception, e:
               import traceback
               print traceback.format_exc()
               pass
           if force_update:
             self._updateDisplay()
         except socket.timeout:
   #        rospy.logwarn("TIMOUT ignored")
           break
         except socket.error:
           import traceback
           rospy.logwarn("socket error: %s", traceback.format_exc())
           break
         except:
예제 #6
0
 def load(self, argv):
     '''
     @param argv: the list with argv parameter needed to load the launch file.
                  The name and value are separated by C{:=}
     @type argv: C{[str]}
     @return True, if the launch file was loaded
     @rtype boolean
     @raise LaunchConfigException: on load errors
     '''
     try:
         roscfg = roslaunch.ROSLaunchConfig()
         loader = roslaunch.XmlLoader()
         self.argv = self.resolveArgs(argv)
         loader.load(self.Filename, roscfg, verbose=False, argv=self.argv)
         self.__roscfg = roscfg
         nm.file_watcher().add_launch(self.__masteruri, self.__launchFile, self.__launch_id, self.getIncludedFiles(self.Filename))
         if not nm.is_local(nm.nameres().getHostname(self.__masteruri)):
             files = self.getIncludedFiles(self.Filename,
                                           regexp_list=[QRegExp("\\bdefault\\b"),
                                                        QRegExp("\\bvalue=.*pkg:\/\/\\b"),
                                                        QRegExp("\\bvalue=.*package:\/\/\\b"),
                                                        QRegExp("\\bvalue=.*\$\(find\\b")])
             nm.file_watcher_param().add_launch(self.__masteruri,
                                                self.__launchFile,
                                                self.__launch_id,
                                                files)
     except roslaunch.XmlParseException, e:
         test = list(re.finditer(r"environment variable '\w+' is not set", str(e)))
         message = str(e)
         if test:
             message = ''.join([message, '\n', 'environment substitution is not supported, use "arg" instead!'])
         raise LaunchConfigException(message)
예제 #7
0
 def __init__(self, launch_file, package=None, masteruri=None, argv=[]):
     '''
     Creates the LaunchConfig object. The launch file will be not loaded on
     creation, first on request of Roscfg value.
     @param launch_file: The absolute or relative path with the launch file.
                        By using relative path a package must be valid for
                        remote launches.
     @type launch_file: C{str}
     @param package:  the package containing the launch file. If None the
                     launch_file will be used to determine the launch file.
                     No remote launches a possible without a valid package.
     @type package: C{str} or C{None}
     @param masteruri: The URL of the ROS master.
     @type masteruri: C{str} or C{None}
     @param argv: the list the arguments needed for loading the given launch file
     @type argv: C{[str]}
     @raise roslaunch.XmlParseException: if the launch file can't be found.
     '''
     QObject.__init__(self)
     self.__launchFile = launch_file
     self.__package = package_name(os.path.dirname(self.__launchFile))[0] if package is None else package
     self.__masteruri = masteruri if masteruri is not None else 'localhost'
     self.__roscfg = None
     self.argv = argv
     self.__reqTested = False
     self.__argv_values = dict()
     self.global_param_done = []  # masteruri's where the global parameters are registered
     self.hostname = nm.nameres().getHostname(self.__masteruri)
     self.__launch_id = '%.9f' % time.time()
     nm.file_watcher().add_launch(self.__masteruri, self.__launchFile, self.__launch_id, [self.__launchFile])
예제 #8
0
 def on_heartbeat_received(self, msg, address, is_multicast):
     force_update = False
     with self.mutex:
         try:
             hostname = self._hosts[address[0]]
         except:
             self.status_text_signal.emit("resolve %s" % address[0])
             hostname = nm.nameres().hostname(utf8(address[0]),
                                              resolve=True)
             self._hosts[address[0]] = hostname
         try:
             (_version,
              _msg_tuple) = Discoverer.msg2masterState(msg, address)
             index = address[1] - self.default_port
             if index not in self._discovered:
                 self._discovered[index] = dict()
             self._discovered[index][address] = (hostname, time.time())
             if hostname not in self._msg_counts:
                 self._msg_counts[hostname] = 0
             self._msg_counts[hostname] += 1
             self._received_msgs += 1
             force_update = True
         except:
             print traceback.format_exc(1)
     if force_update:
         self._updateDisplay()
예제 #9
0
    def updateTypeView(cls, service, item):
        '''
        Updates the representation of the column contains the type of the service.
        @param service: the service data
        @type service: L{master_discovery_fkie.ServiceInfo}
        @param item: corresponding item in the model
        @type item: L{ServiceItem}
        '''
        try:
            if service.isLocal and service.type:
                service_class = service.get_service_class(nm.is_local(nm.nameres().getHostname(service.uri)))
                item.setText(service_class._type)
            elif service.type:
                item.setText(service.type)
            else:
                item.setText('unknown type')
            # removed tooltip for clarity !!!
#      tooltip = ''
#      tooltip = ''.join([tooltip, '<h4>', service_class._type, '</h4>'])
#      tooltip = ''.join([tooltip, '<b><u>', 'Request', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', str(service_class._request_class.__slots__), '</dt></dl>'])
#
#      tooltip = ''.join([tooltip, '<b><u>', 'Response', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', str(service_class._response_class.__slots__), '</dt></dl>'])
#
#      item.setToolTip(''.join(['<div>', tooltip, '</div>']))
            item.setToolTip('')
        except:
            if not service.isLocal:
                tooltip = ''.join(['<h4>', 'Service type is not available due to he running on another host.', '</h4>'])
                item.setToolTip(''.join(['<div>', tooltip, '</div>']))
예제 #10
0
  def updateModelData(self, nodes):
    '''
    Updates the model data.
    @param nodes: a dictionary with name and info objects of the nodes.
    @type nodes: C{dict(str:L{NodeInfo}, ...)}
    '''
    # separate into different hosts
    hosts = dict()
    for (name, node) in nodes.items():
      host = (node.masteruri, nm.nameres().getHostname(node.uri if not node.uri is None else node.masteruri))
      if not hosts.has_key(host):
        hosts[host] = dict()
      hosts[host][name] = node
    # update nodes for each host
    for ((masteruri, host), nodes_filtered) in hosts.items():
      hostItem = self.getHostItem(masteruri, host)
      # rename the host item if needed
      if not hostItem is None:
#        host_name = nm.nameres().getName(host=host)
#        if host_name and not (hostItem.name == host_name):
#          hostItem.name = host_name
        hostItem.updateRunningNodeState(nodes_filtered)
    # update nodes of the hosts, which are not more exists
    for i in reversed(range(self.invisibleRootItem().rowCount())):
      host = self.invisibleRootItem().child(i)
      if not hosts.has_key(host.id):
        host.updateRunningNodeState({})
    self.removeEmptyHosts()
    def updateCapabilities(self, masteruri, cfg_name, description):
        '''
        Updates the capabilities view.
        @param masteruri: the ROS master URI of updated ROS master.
        @type masteruri: C{str}
        @param cfg_name: The name of the node provided the capabilities description.
        @type cfg_name: C{str}
        @param description: The capabilities description object.
        @type description: U{multimaster_msgs_fkie.srv.ListDescription<http://docs.ros.org/api/multimaster_msgs_fkie/html/srv/ListDescription.html>} Response
        '''
        # if it is a new masteruri add a new column
        robot_index = self._robotHeader.index(masteruri)
        robot_name = description.robot_name if description.robot_name else nm.nameres().mastername(masteruri)
        # append a new robot
        new_robot = False
        if robot_index == -1:
            robot_index = self._robotHeader.insertSortedItem(masteruri, robot_name)
            self.insertColumn(robot_index)
#      robot_index = self.columnCount()-1
#      self._robotHeader.insertItem(robot_index)
            self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)
            item = QTableWidgetItem()
            item.setSizeHint(QSize(96, 96))
            self.setHorizontalHeaderItem(robot_index, item)
            self.horizontalHeaderItem(robot_index).setText(robot_name)
            new_robot = True
        else:
            # update
            self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)

        # set the capabilities
        for c in description.capabilities:
            cap_index = self._capabilityHeader.index(c.name.decode(sys.getfilesystemencoding()))
            if cap_index == -1 or new_robot:
                if cap_index == -1:
                    # append a new capability
                    cap_index = self._capabilityHeader.insertSortedItem(c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()))
                    self.insertRow(cap_index)
                    self.setRowHeight(cap_index, 96)
                    self._capabilityHeader.setDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
                    item = QTableWidgetItem()
                    item.setSizeHint(QSize(96, 96))
                    self.setVerticalHeaderItem(cap_index, item)
                    self.verticalHeaderItem(cap_index).setText(c.name.decode(sys.getfilesystemencoding()))
                else:
                    self._capabilityHeader.setDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
                # add the capability control widget
                controlWidget = CapabilityControlWidget(masteruri, cfg_name, c.namespace, c.nodes)
                controlWidget.start_nodes_signal.connect(self._start_nodes)
                controlWidget.stop_nodes_signal.connect(self._stop_nodes)
                self.setCellWidget(cap_index, robot_index, controlWidget)
                self._capabilityHeader.controlWidget.insert(cap_index, controlWidget)
            else:
                self._capabilityHeader.updateDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
                try:
                    self.cellWidget(cap_index, robot_index).updateNodes(cfg_name, c.namespace, c.nodes)
                except:
                    import traceback
                    print traceback.format_exc()
예제 #12
0
  def updateDispayedName(self, item, show_ros_names):
    '''
    Updates the name representation of the given QStandardItem
    @param item: item which represent the URI 
    @type item: L{PySide.QtGui.QStandardItem}
    @param show_ros_names: show the as ROS names or as their description.
    @type show_ros_names: C{bool}
    '''
    if self.descr_name and not show_ros_names:
      item.setText(self.descr_name)
    else:
      item.setText(NodeItem.toHTML(self.name))
    tooltip = ''.join(['<html><body><h4>', self.name, '</h4><dl>'])
    tooltip = ''.join([tooltip, '<dt>PID: ', str(self.pid), '</dt></dl>'])
    uri = nm.nameres().getUri(host=nm.nameres().getHostname(self.uri))
    master_discovered = (not uri is None)
    local = (nm.nameres().getHostname(self.uri) == nm.nameres().getHostname(self.masteruri))
    if not self.pid is None:
      item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
    elif not local and not master_discovered and not self.uri is None:
      item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
      tooltip = ''.join([tooltip, '<dl><dt>(Remote nodes will not be ping, so they are always marked running)</dt></dl>'])
#    elif not master_discovered and not self.uri is None:
#      item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
    elif not self.uri is None:
      item.setIcon(QtGui.QIcon(':/icons/crystal_clear_warning.png'))
      if not local and master_discovered:
        tooltip = ''.join(['<h4>', self.name, ' is not local, however the ROS master on this host is discovered, but no information about this node received!', '</h4>'])
    else:
      item.setIcon(QtGui.QIcon())

    if self.descr_type or self.descr_name or self.descr:
      tooltip = ''.join([tooltip, '<b><u>Detailed description:</u></b>'])
      if self.descr_type:
        tooltip = ''.join([tooltip, '<dl><dt><b>Sensor type:</b> ', self.descr_type, '</dt>'])
      if self.descr_name:
        tooltip = ''.join([tooltip, '<dt><b>Sensor name:</b> ', self.descr_name, '</dt></dl>'])
      if self.descr:
        try:
          from docutils import examples
          tooltip = ''.join([tooltip, examples.html_body(self.descr, input_encoding='utf8')])
        except:
          import traceback
          rospy.logwarn("Error while generate description for a node: %s", str(traceback.format_exc()))
    tooltip = ''.join([tooltip, '</dl></body></html>'])
    item.setToolTip(tooltip)
예제 #13
0
 def updateModelData(self, nodes_extended, onhost):
     '''
 Updates the model data.
 @param nodes_extended: a dictionary with name and extended info of the nodes.
 @type nodes_extended: C{dict(node name : L{ExtendedNodeInfo}, ...)}
 @param onhost: the displayed host
 @type onhost: C{str}
 '''
     #remove old nodes from the list
     nodes = nodes_extended.keys()
     for i in reversed(range(self.invisibleRootItem().rowCount())):
         host = self.invisibleRootItem().child(i)
         if not host is None:  # should not occur
             for j in reversed(range(host.rowCount())):
                 nodeItem = host.child(j)
                 if not nodeItem.node.name in nodes:
                     nodeItem.node.updateRunState(
                         ExtendedNodeInfo(nodeItem.node.name, None, None,
                                          None, None))
                     if self.canBeremoved(nodeItem.node):
                         host.removeRow(j)
                     else:
                         nodeItem.updateNodeView(host, self.show_rosnames)
                 elif nodes_extended[
                         nodeItem.node.
                         name].uri != nodeItem.node.uri and not nodeItem.node.cfgs and not nodeItem.node.default_cfgs:
                     # if the node was started on the other host, remove the current existing
                     host.removeRow(j)
         else:
             return
         if host.rowCount() == 0:
             self.invisibleRootItem().removeRow(i)
     for (name, node) in nodes_extended.items():
         # create parent items for different hosts
         host = nm.nameres().getHostname(
             node.uri if not node.uri is None else node.masteruri)
         if not host is None:
             hostItem = self.getHostItem(host, node.masteruri, onhost)
             doAddItem = True
             for i in range(hostItem.rowCount()):
                 nodeItem = hostItem.child(i)
                 if (nodeItem == node.name):
                     # update item
                     nodeItem.node.updateRunState(node)
                     nodeItem.updateNodeView(hostItem, self.show_rosnames)
                     doAddItem = False
                     break
                 elif (hostItem.child(i) > node.name):
                     hostItem.insertRow(
                         i, NodeItem.getItemList(node, self.show_rosnames))
                     doAddItem = False
                     break
             if doAddItem:
                 hostItem.appendRow(
                     NodeItem.getItemList(node, self.show_rosnames))
         else:  # should not happen!
             print "node IGNORED", name, " - no host detected, uri:", node.uri, ", masteruri:", node.masteruri
  def updateMaster(self, master):
    '''
    Updates the information of the ros master. If the ROS master not exists, it 
    will be added.
    
    @param master: the ROS master to update
    @type master: L{master_discovery_fkie.msg.ROSMaster}
    '''
    # remove master, if his name was changed but not the ROS master URI
    root = self.invisibleRootItem()
    for i in reversed(range(root.rowCount())):
      masterItem = root.child(i)
      if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
        root.removeRow(i)
        try:
          del self.pyqt_workaround[masterItem.master.name]
        except:
          pass
        break

    # update or add a the item
    root = self.invisibleRootItem()
    doAddItem = True
    for i in range(root.rowCount()):
      masterItem = root.child(i, self.COL_NAME)
      if (masterItem == master.name):
        # update item
        masterItem.master = master
        masterItem.updateMasterView(root)
        doAddItem = False
        break
      elif (masterItem > master.name):
        mitem = MasterItem.getItemList(master, (nm.is_local(nm.nameres().getHostname(master.uri))))
        self.pyqt_workaround[master.name] = mitem  # workaround for using with PyQt: store the python object to keep the defined attributes in the MasterItem subclass
        root.insertRow(i, mitem)
        mitem[self.COL_NAME].parent_item = root
        doAddItem = False
        break
    if doAddItem:
      mitem = MasterItem.getItemList(master, (nm.is_local(nm.nameres().getHostname(master.uri))))
      self.pyqt_workaround[master.name] = mitem  # workaround for using with PyQt: store the python object to keep the defined attributes in the MasterItem subclass
      root.appendRow(mitem)
      mitem[self.COL_NAME].parent_item = root
예제 #15
0
 def hostNameFrom(cls, masteruri, address):
   '''
   Returns the name generated from masteruri and address
   @param masteruri: URI of the ROS master assigned to the host
   @type masteruri: C{str}
   @param address: the address of the host
   @type address: C{str}
   '''
   #'print "hostNameFrom - mastername"
   name = nm.nameres().mastername(masteruri, address)
   if not name:
     name = address
   #'print "hostNameFrom - hostname"
   hostname = nm.nameres().hostname(address)
   if hostname is None:
     hostname = str(address)
   result = '@'.join([name, hostname])
   if nm.nameres().getHostname(masteruri) != hostname:
     result = ''.join([result, '[', masteruri,']'])
   #'print "- hostNameFrom"
   return result
    def updateMaster(self, master):
        '''
    Updates the information of the ros master. If the ROS master not exists, it 
    will be added.
    
    @param master: the ROS master to update
    @type master: L{master_discovery_fkie.msg.ROSMaster}
    '''
        # remove master, if his name was changed but not the ROS master URI
        root = self.invisibleRootItem()
        for i in reversed(range(root.rowCount())):
            masterItem = root.child(i)
            if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
                root.removeRow(i)
                break

        # update or add a the item
        root = self.invisibleRootItem()
        doAddItem = True
        for i in range(root.rowCount()):
            masterItem = root.child(i)
            if (masterItem == master.name):
                # update item
                masterItem.master = master
                masterItem.updateMasterView(root)
                doAddItem = False
                break
            elif (masterItem > master.name):
                mitem = MasterItem.getItemList(
                    master,
                    (nm.is_local(nm.nameres().getHostname(master.uri))))
                root.insertRow(i, mitem)
                mitem[0].parent_item = root
                doAddItem = False
                break
        if doAddItem:
            mitem = MasterItem.getItemList(
                master, (nm.is_local(nm.nameres().getHostname(master.uri))))
            root.appendRow(mitem)
            mitem[0].parent_item = root
예제 #17
0
    def _load_parameters(cls, masteruri, params, clear_params, user, pw,
                         auto_pw_request):
        """
    Load parameters onto the parameter server
    """
        import roslaunch
        import roslaunch.launch
        param_server = xmlrpclib.ServerProxy(masteruri)
        p = None
        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # packages names
        try:
            socket.setdefaulttimeout(6 + len(clear_params))
            # multi-call style xmlrpc
            param_server_multi = xmlrpclib.MultiCall(param_server)

            # clear specified parameter namespaces
            # #2468 unify clear params to prevent error
            for p in clear_params:
                param_server_multi.deleteParam(rospy.get_name(), p)
            r = param_server_multi()
            for code, msg, _ in r:
                if code != 1 and not msg.find("is not set"):
                    rospy.logwarn("Failed to clear parameter: %s", msg)
#          raise StartException("Failed to clear parameter: %s"%(msg))

# multi-call objects are not reusable
            socket.setdefaulttimeout(6 + len(params))
            param_server_multi = xmlrpclib.MultiCall(param_server)
            for p in params.itervalues():
                # suppressing this as it causes too much spam
                value, is_abs_path, found, package = cls._resolve_abs_paths(
                    p.value,
                    nm.nameres().address(masteruri), user, pw, auto_pw_request)
                if is_abs_path:
                    abs_paths.append((p.key, p.value, value))
                    if not found and package:
                        not_found_packages.append(package)
                if p.value is None:
                    rospy.logwarn("The parameter '%s' is invalid: '%s'" %
                                  (p.key, p.value))
                    #raise StartException("The parameter '%s' is invalid: '%s'"%(p.key, p.value))
                else:
                    param_server_multi.setParam(
                        rospy.get_name(), p.key,
                        value if is_abs_path else p.value)
            r = param_server_multi()
            for code, msg, _ in r:
                if code != 1:
                    raise StartException("Failed to set parameter: %s" % (msg))
        except roslaunch.core.RLException, e:
            raise StartException(e)
예제 #18
0
 def updateDispayedName(self):
   '''
   Updates the name representation of the Item
   '''
   tooltip = ''.join(['<h4>', self.node_info.name, '</h4><dl>'])
   tooltip = ''.join([tooltip, '<dt><b>URI:</b> ', str(self.node_info.uri), '</dt>'])
   tooltip = ''.join([tooltip, '<dt><b>PID:</b> ', str(self.node_info.pid), '</dt></dl>'])
   master_discovered = nm.nameres().hasMaster(self.node_info.masteruri)
   local = False
   if not self.node_info.uri is None and not self.node_info.masteruri is None:
     local = (nm.nameres().getHostname(self.node_info.uri) == nm.nameres().getHostname(self.node_info.masteruri))
   if not self.node_info.pid is None:
     self._state = NodeItem.STATE_RUN
     self.setIcon(QtGui.QIcon(':/icons/state_run.png'))
     self.setToolTip('')
   elif not local and not master_discovered and not self.node_info.uri is None:
     self._state = NodeItem.STATE_RUN
     self.setIcon(QtGui.QIcon(':/icons/state_run.png'))
     tooltip = ''.join([tooltip, '<dl><dt>(Remote nodes will not be ping, so they are always marked running)</dt></dl>'])
     tooltip = ''.join([tooltip, '</dl>'])
     self.setToolTip(''.join(['<div>', tooltip, '</div>']))
   elif not self.node_info.uri is None:
     self._state = NodeItem.STATE_WARNING
     self.setIcon(QtGui.QIcon(':/icons/crystal_clear_warning.png'))
     if not local and master_discovered:
       tooltip = ''.join(['<h4>', self.node_info.name, ' is not local, however the ROS master on this host is discovered, but no information about this node received!', '</h4>'])
       tooltip = ''.join([tooltip, '</dl>'])
       self.setToolTip(''.join(['<div>', tooltip, '</div>']))
   elif self.has_running:
     self._state = NodeItem.STATE_DUPLICATE
     self.setIcon(QtGui.QIcon(':/icons/imacadam_stop.png'))
     tooltip = ''.join(['<h4>Where are nodes with the same name on remote hosts running. These will be terminated, if you run this node! (Only if master_sync is running or will be started somewhere!)</h4>'])
     tooltip = ''.join([tooltip, '</dl>'])
     self.setToolTip(''.join(['<div>', tooltip, '</div>']))
   else:
     self._state = NodeItem.STATE_OFF
     self.setIcon(QtGui.QIcon(':/icons/state_off.png'))
     self.setToolTip('')
  def updateCapabilities(self, masteruri, cfg_name, description):
    '''
    Updates the capabilities view.
    @param masteruri: the ROS master URI of updated ROS master.
    @type masteruri: C{str}
    @param cfg_name: The name of the node provided the capabilities description.
    @type cfg_name: C{str}
    @param description: The capabilities description object.
    @type description: L{default_cfg_fkie.Description}
    '''
    # if it is a new masteruri add a new column
    robot_index = self._robotHeader.index(masteruri)
    robot_name = description.robot_name if description.robot_name else nm.nameres().mastername(masteruri)
    if robot_index == -1:
      # append a new robot
      robot_index = self._robotHeader.insertSortedItem(masteruri, robot_name)
      self.insertColumn(robot_index)
#      robot_index = self.columnCount()-1
#      self._robotHeader.insertItem(robot_index)
      self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)
      item = QtGui.QTableWidgetItem()
      item.setSizeHint(QtCore.QSize(96,96))
      self.setHorizontalHeaderItem(robot_index, item)
      self.horizontalHeaderItem(robot_index).setText(robot_name)
    else:
      #update
      self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)
    
    #set the capabilities
    for c in description.capabilities:
      cap_index = self._capabilityHeader.index(c.name.decode(sys.getfilesystemencoding()))
      if cap_index == -1:
        # append a new capability
        cap_index = self._capabilityHeader.insertSortedItem(c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()))
        self.insertRow(cap_index)
        self.setRowHeight(cap_index, 96)
        self._capabilityHeader.setDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
        item = QtGui.QTableWidgetItem()
        item.setSizeHint(QtCore.QSize(96,96))
        self.setVerticalHeaderItem(cap_index, item)
        self.verticalHeaderItem(cap_index).setText(c.name.decode(sys.getfilesystemencoding()))
        # add the capability control widget
        controlWidget = CapabilityControlWidget(masteruri, cfg_name, c.namespace, c.nodes)
        controlWidget.start_nodes_signal.connect(self._start_nodes)
        controlWidget.stop_nodes_signal.connect(self._stop_nodes)
        self.setCellWidget(cap_index, robot_index, controlWidget)
        self._capabilityHeader.controlWidget.insert(cap_index, controlWidget)
      else:
        self._capabilityHeader.updateDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
        self._capabilityHeader.controlWidget[cap_index].updateNodes(cfg_name, c.namespace, c.nodes)
예제 #20
0
 def updateModelData(self, nodes_extended, onhost):
   '''
   Updates the model data.
   @param nodes_extended: a dictionary with name and extended info of the nodes.
   @type nodes_extended: C{dict(node name : L{ExtendedNodeInfo}, ...)}
   @param onhost: the displayed host
   @type onhost: C{str}
   '''
   #remove old nodes from the list
   nodes = nodes_extended.keys()
   for i in reversed(range(self.invisibleRootItem().rowCount())):
     host = self.invisibleRootItem().child(i)
     if not host is None: # should not occur
       for j in reversed(range(host.rowCount())):
         nodeItem = host.child(j)
         if not nodeItem.node.name in nodes:
           nodeItem.node.updateRunState(ExtendedNodeInfo(nodeItem.node.name, None, None, None, None))
           if self.canBeremoved(nodeItem.node):
             host.removeRow(j)
           else:
             nodeItem.updateNodeView(host, self.show_rosnames)
         elif nodes_extended[nodeItem.node.name].uri != nodeItem.node.uri and not nodeItem.node.cfgs and not nodeItem.node.default_cfgs:
           # if the node was started on the other host, remove the current existing
           host.removeRow(j)
     else:
       return
     if host.rowCount() == 0:
       self.invisibleRootItem().removeRow(i)
   for (name, node) in nodes_extended.items():
     # create parent items for different hosts
     host = nm.nameres().getHostname(node.uri if not node.uri is None else node.masteruri)
     if not host is None:
       hostItem = self.getHostItem(host, node.masteruri, onhost)
       doAddItem = True
       for i in range(hostItem.rowCount()):
         nodeItem = hostItem.child(i)
         if (nodeItem == node.name):
           # update item
           nodeItem.node.updateRunState(node)
           nodeItem.updateNodeView(hostItem, self.show_rosnames)
           doAddItem = False
           break
         elif (hostItem.child(i) > node.name):
           hostItem.insertRow(i, NodeItem.getItemList(node, self.show_rosnames))
           doAddItem = False
           break
       if doAddItem:
         hostItem.appendRow(NodeItem.getItemList(node, self.show_rosnames))
     else: # should not happen!
       print "node IGNORED", name, " - no host detected, uri:", node.uri, ", masteruri:", node.masteruri
예제 #21
0
  def updateCapabilities(self, masteruri, cfg_name, description):
    '''
    Updates the capabilities view.
    @param masteruri: the ROS master URI of updated ROS master.
    @type masteruri: C{str}
    @param cfg_name: The name of the node provided the capabilities description.
    @type cfg_name: C{str}
    @param description: The capabilities description object.
    @type description: L{default_cfg_fkie.Description}
    '''
    # if it is a new masteruri add a new column
    robot_index = self._robotHeader.index(masteruri)
    robot_name = description.robot_name if description.robot_name else nm.nameres().mastername(masteruri)
    if robot_index == -1:
      # append a new robot
      robot_index = self._robotHeader.insertSortedItem(masteruri, robot_name)
      self.insertColumn(robot_index)
#      robot_index = self.columnCount()-1
#      self._robotHeader.insertItem(robot_index)
      self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)
      item = QtGui.QTableWidgetItem()
      item.setSizeHint(QtCore.QSize(96,96))
      self.setHorizontalHeaderItem(robot_index, item)
      self.horizontalHeaderItem(robot_index).setText(robot_name)
    else:
      #update
      self._robotHeader.setDescription(robot_index, cfg_name, masteruri, robot_name, description.robot_type, description.robot_descr.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), description.robot_images)
    
    #set the capabilities
    for c in description.capabilities:
      cap_index = self._capabilityHeader.index(c.name.decode(sys.getfilesystemencoding()))
      if cap_index == -1:
        # append a new capability
        cap_index = self._capabilityHeader.insertSortedItem(c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()))
        self.insertRow(cap_index)
        self.setRowHeight(cap_index, 96)
        self._capabilityHeader.setDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
        item = QtGui.QTableWidgetItem()
        item.setSizeHint(QtCore.QSize(96,96))
        self.setVerticalHeaderItem(cap_index, item)
        self.verticalHeaderItem(cap_index).setText(c.name.decode(sys.getfilesystemencoding()))
        # add the capability control widget
        controlWidget = CapabilityControlWidget(masteruri, cfg_name, c.namespace, c.nodes)
        controlWidget.start_nodes_signal.connect(self._start_nodes)
        controlWidget.stop_nodes_signal.connect(self._stop_nodes)
        self.setCellWidget(cap_index, robot_index, controlWidget)
        self._capabilityHeader.controlWidget.insert(cap_index, controlWidget)
      else:
        self._capabilityHeader.updateDescription(cap_index, cfg_name, c.name.decode(sys.getfilesystemencoding()), c.name.decode(sys.getfilesystemencoding()), c.type, c.description.replace("\\n ", "\n").decode(sys.getfilesystemencoding()), c.images)
        self._capabilityHeader.controlWidget[cap_index].updateNodes(cfg_name, c.namespace, c.nodes)
    def _load_parameters(cls, masteruri, params, clear_params, user, pw, auto_pw_request):
        """
        Load parameters onto the parameter server
        """
        import roslaunch
        import roslaunch.launch
        param_server = xmlrpclib.ServerProxy(masteruri)
        p = None
        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # packages names
        param_errors = []
        try:
            socket.setdefaulttimeout(6 + len(clear_params))
            # multi-call style xmlrpc
            param_server_multi = xmlrpclib.MultiCall(param_server)

            # clear specified parameter namespaces
            # #2468 unify clear params to prevent error
            for p in clear_params:
                param_server_multi.deleteParam(rospy.get_name(), p)
            r = param_server_multi()
            for code, msg, _ in r:
                if code != 1 and not msg.find("is not set"):
                    rospy.logwarn("Failed to clear parameter: %s", msg)
#          raise StartException("Failed to clear parameter: %s"%(msg))

            # multi-call objects are not reusable
            socket.setdefaulttimeout(6 + len(params))
            param_server_multi = xmlrpclib.MultiCall(param_server)
            address = nm.nameres().address(masteruri)
            for p in params.itervalues():
                # suppressing this as it causes too much spam
                value, is_abs_path, found, package = cls._resolve_abs_paths(p.value, address, user, pw, auto_pw_request)
                if is_abs_path:
                    abs_paths.append((p.key, p.value, value))
                    if not found and package:
                        not_found_packages.append(package)
#         if p.value is None:
#           rospy.logwarn("The parameter '%s' is invalid: '%s'"%(p.key, p.value))
                    # raise StartException("The parameter '%s' is invalid: '%s'"%(p.key, p.value))
                param_server_multi.setParam(rospy.get_name(), p.key, value if is_abs_path else p.value)
                test_ret = cls._test_value(p.key, value if is_abs_path else p.value)
                if test_ret:
                    param_errors.extend(test_ret)
            r = param_server_multi()
            for code, msg, _ in r:
                if code != 1:
                    raise StartException("Failed to set parameter: %s" % (msg))
        except roslaunch.core.RLException, e:
            raise StartException(e)
 def on_heartbeat_received(self, msg, address, is_multicast):
     force_update = False
     with self.mutex:
         try:
             hostname = self._hosts[address[0]]
         except:
             self.status_text_signal.emit("resolve %s" % address[0])
             hostname = nm.nameres().hostname(str(address[0]), resolve=True)
             self._hosts[address[0]] = hostname
         try:
             (_version, _msg_tuple) = Discoverer.msg2masterState(msg, address)
             index = address[1] - self.default_port
             if index not in self._discovered:
                 self._discovered[index] = dict()
             self._discovered[index][address] = (hostname, time.time())
             self._received_msgs += 1
             force_update = True
         except:
             print traceback.format_exc(1)
     if force_update:
         self._updateDisplay()
 def on_heartbeat_received(self, msg, address):
     force_update = False
     with self.mutex:
         try:
             hostname = self._hosts[address[0]]
         except:
             self.status_text_signal.emit("resolve %s" % address[0])
             hostname = nm.nameres().hostname(str(address[0]), resolve=True)
             self._hosts[address[0]] = hostname
         try:
             (version, msg_tuple) = Discoverer.msg2masterState(msg, address)
             index = address[1] - self.default_port
             if not self._discovered.has_key(index):
                 self._discovered[index] = dict()
             self._discovered[index][address] = (hostname, time.time())
             self._received_msgs += 1
             force_update = True
         except:
             print traceback.format_exc(1)
     if force_update:
         self._updateDisplay()
  def updateMaster(self, master):
    '''
    Updates the information of the ros master. If the ROS master not exists, it 
    will be added.
    
    @param master: the ROS master to update
    @type master: L{master_discovery_fkie.msg.ROSMaster}
    '''
    # remove master, if his name was changed but not the ROS master URI
    root = self.invisibleRootItem()
    for i in reversed(range(root.rowCount())):
      masterItem = root.child(i)
      if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
        root.removeRow(i)
        try:
          del self.pyqt_workaround[masterItem.master.name]
        except:
          pass
        break

    # update or add a the item
    root = self.invisibleRootItem()
    doAddItem = True
    is_local = nm.is_local(nm.nameres().getHostname(master.uri))
    for index in range(root.rowCount()):
      masterItem = root.child(index, self.COL_NAME)
      if (masterItem == master.name):
        # update item
        masterItem.master = master
        masterItem.updateMasterView(root)
        doAddItem = False
        break
      elif (masterItem > master.name):
        self.addRow(master, is_local, root, index)
        doAddItem = False
        break
    if doAddItem:
      self.addRow(master, is_local, root, -1)
예제 #26
0
    def updateMaster(self, master):
        '''
    Updates the information of the ros master. If the ROS master not exists, it 
    will be added.
    
    @param master: the ROS master to update
    @type master: L{master_discovery_fkie.msg.ROSMaster}
    '''
        # remove master, if his name was changed but not the ROS master URI
        root = self.invisibleRootItem()
        for i in reversed(range(root.rowCount())):
            masterItem = root.child(i)
            if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
                root.removeRow(i)
                try:
                    del self.pyqt_workaround[masterItem.master.name]
                except:
                    pass
                break

        # update or add a the item
        root = self.invisibleRootItem()
        doAddItem = True
        is_local = nm.is_local(nm.nameres().getHostname(master.uri))
        for index in range(root.rowCount()):
            masterItem = root.child(index, self.COL_NAME)
            if (masterItem == master.name):
                # update item
                masterItem.master = master
                masterItem.updateMasterView(root)
                doAddItem = False
                break
            elif (masterItem > master.name):
                self.addRow(master, is_local, root, index)
                doAddItem = False
                break
        if doAddItem:
            self.addRow(master, is_local, root, -1)
예제 #27
0
    def updateDispayedName(self, item, show_ros_names):
        '''
    Updates the name representation of the given QStandardItem
    @param item: item which represent the URI 
    @type item: L{PySide.QtGui.QStandardItem}
    @param show_ros_names: show the as ROS names or as their description.
    @type show_ros_names: C{bool}
    '''
        if self.descr_name and not show_ros_names:
            item.setText(self.descr_name)
        else:
            item.setText(NodeItem.toHTML(self.name))
        tooltip = ''.join(['<html><body><h4>', self.name, '</h4><dl>'])
        tooltip = ''.join([tooltip, '<dt>PID: ', str(self.pid), '</dt></dl>'])
        uri = nm.nameres().getUri(host=nm.nameres().getHostname(self.uri))
        master_discovered = (not uri is None)
        local = (nm.nameres().getHostname(
            self.uri) == nm.nameres().getHostname(self.masteruri))
        if not self.pid is None:
            item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
        elif not local and not master_discovered and not self.uri is None:
            item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
            tooltip = ''.join([
                tooltip,
                '<dl><dt>(Remote nodes will not be ping, so they are always marked running)</dt></dl>'
            ])
#    elif not master_discovered and not self.uri is None:
#      item.setIcon(QtGui.QIcon(':/icons/state_run.png'))
        elif not self.uri is None:
            item.setIcon(QtGui.QIcon(':/icons/crystal_clear_warning.png'))
            if not local and master_discovered:
                tooltip = ''.join([
                    '<h4>', self.name,
                    ' is not local, however the ROS master on this host is discovered, but no information about this node received!',
                    '</h4>'
                ])
        else:
            item.setIcon(QtGui.QIcon())

        if self.descr_type or self.descr_name or self.descr:
            tooltip = ''.join([tooltip, '<b><u>Detailed description:</u></b>'])
            if self.descr_type:
                tooltip = ''.join([
                    tooltip, '<dl><dt><b>Sensor type:</b> ', self.descr_type,
                    '</dt>'
                ])
            if self.descr_name:
                tooltip = ''.join([
                    tooltip, '<dt><b>Sensor name:</b> ', self.descr_name,
                    '</dt></dl>'
                ])
            if self.descr:
                try:
                    from docutils import examples
                    tooltip = ''.join([
                        tooltip,
                        examples.html_body(self.descr, input_encoding='utf8')
                    ])
                except:
                    import traceback
                    rospy.logwarn(
                        "Error while generate description for a node: %s",
                        str(traceback.format_exc()))
        tooltip = ''.join([tooltip, '</dl></body></html>'])
        item.setToolTip(tooltip)
 def on_save_profile(self, masteruri='', path=None):
     '''
     Saves the current environment to a node manager profile.
     :param path: the pach the file to save
     :type path: str
     :param masteruri: If not empty, save the profile only for given master
     :type masteruri: str
     '''
     try:
         if path is None:
             path = self.get_profile_file()
             if path is None:
                 return
         rospy.loginfo("Save profile %s" % path)
         import yaml
         content = {}
         for muri, master in self._main_window.masters.items():
             if not masteruri or masteruri == muri:
                 running_nodes = master.getRunningNodesIfLocal()
                 configs = {}
                 md_param = {}
                 ms_param = {}
                 zc_param = {}
                 smuri = muri
                 addr = nm.nameres().address(smuri)
                 hostname = get_hostname(smuri)
                 mastername = ''
                 if nm.is_local(addr):
                     smuri = smuri.replace(hostname, '$LOCAL$')
                     addr = '$LOCAL$'
                 else:
                     mastername = nm.nameres().mastername(smuri, nm.nameres().address(smuri))
                 for node_name in running_nodes.keys():
                     node_items = master.getNode(node_name)
                     for node in node_items:
                         if node.is_running() and node.launched_cfg is not None:  # node.has_launch_cfgs(node.cfgs):
                             cfg = node.launched_cfg
                             if isinstance(node.launched_cfg, (str, unicode)):
                                 # it is default config
                                 cfg = node.launched_cfg.replace("/%s" % hostname, '/$LOCAL$').rstrip('/run')
                             else:
                                 # it is a loaded launch file, get the filename
                                 cfg = to_url(node.launched_cfg.Filename)
                             if cfg not in configs:
                                 configs[cfg] = {'nodes': []}
                             configs[cfg]['nodes'].append(node_name)
                         elif node_name.endswith('master_discovery'):
                             md_param = get_rosparam('master_discovery', muri)
                         elif node_name.endswith('master_sync'):
                             ms_param = get_rosparam('master_sync', muri)
                         elif node_name.endswith('zeroconf'):
                             zc_param = get_rosparam('zeroconf', muri)
                         elif node_name.endswith('default_cfg'):
                             # store parameter for default configuration
                             nn = node_name.replace("/%s" % hostname, '/$LOCAL$')
                             if nn not in configs:
                                 configs[nn] = {'nodes': []}
                             configs[nn]['params'] = get_rosparam(node_name, muri)
                             configs[nn]['default'] = True
                 # store arguments for launchfiles
                 for a, b in master.launchfiles.items():
                     resolved_a = to_url(a)
                     if resolved_a not in configs:
                         if resolved_a.endswith('default_cfg/run'):
                             pass
                         else:
                             configs[resolved_a] = {}
                             configs[resolved_a]['default'] = False
                     configs[resolved_a]['argv'] = b.argv
                 # fill the configuration content for yaml as dictionary
                 content[smuri] = {'mastername': mastername,
                                   'address': addr,
                                   'configs': configs}
                 if md_param:
                     content[smuri]['master_discovery'] = md_param
                 if ms_param:
                     content[smuri]['master_sync'] = ms_param
                 if zc_param:
                     content[smuri]['zeroconf'] = zc_param
         text = yaml.dump(content, default_flow_style=False)
         with open(path, 'w+') as f:
             f.write(text)
     except Exception as e:
         import traceback
         print utf8(traceback.format_exc(3))
         MessageBox.warning(self, "Save profile Error",
                            'Error while save profile',
                            utf8(e))
예제 #29
0
  def runNode(cls, node, launch_config):
    '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
    n = launch_config.getNode(node)
    if n is None:
      raise StartException(''.join(["Node '", node, "' not found!"]))
    
    env = list(n.env_args)
    prefix = n.launch_prefix if not n.launch_prefix is None else ''
    # thus the parameters while the transfer are not separated
    if prefix:
      prefix = ''.join(['"', prefix, '"'])
    args = [''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])]
    if not (n.cwd is None):
      args.append(''.join(['__cwd:=', n.cwd]))
    
    # add remaps
    for remap in n.remap_args:
      args.append(''.join([remap[0], ':=', remap[1]]))

    # get host of the node
    host = launch_config.hostname
    env_loader = ''
    if n.machine_name:
      machine = launch_config.Roscfg.machines[n.machine_name]
      host = machine.address
      #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader

    masteruri = nm.nameres().getUri(host=host)
    # set the ROS_MASTER_URI
    if masteruri is None:
      env.append(('ROS_MASTER_URI', nm.masteruri_from_ros()))

    # set the global parameter
    if not masteruri is None and not masteruri in launch_config.global_param_done:
      global_node_names = cls.getGlobalParams(launch_config.Roscfg)
      rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names))
      cls._load_parameters(masteruri, global_node_names, [])
      launch_config.global_param_done.append(masteruri)

    # add params
    if not masteruri is None:
      nodens = ''.join([n.namespace, n.name, '/'])
      params = dict()
      for param, value in launch_config.Roscfg.params.items():
        if param.startswith(nodens):
          params[param] = value
      clear_params = []
      for cparam in launch_config.Roscfg.clear_params:
        if cparam.startswith(nodens):
          clear_params.append(param)
      rospy.loginfo("Register parameter:\n%s", '\n'.join(params))
      cls._load_parameters(masteruri, params, clear_params)
    if nm.is_local(host): 
      nm.screen().testScreen()
      try:
        cmd = roslib.packages.find_node(n.package, n.type)
      except (Exception, roslib.packages.ROSPkgException) as e:
        # multiple nodes, invalid package
        raise StartException(''.join(["Can't find resource: ", str(e)]))
      # handle diferent result types str or array of string
      import types
      if isinstance(cmd, types.StringTypes):
        cmd = [cmd]
      cmd_type = ''
      if cmd is None or len(cmd) == 0:
        raise nm.StartException(' '.join([n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n']))
      if len(cmd) > 1:
        # Open selection for executables
        try:
          from PySide import QtGui
          item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', n.type, 'in', n.package]),
                                            'Select an executable',
                                            cmd, 0, False)
          if result:
            #open the selected screen
            cmd_type = item
          else:
            return
        except:
          raise nm.StartException('Multiple executables with same name in package found!')
      else:
        cmd_type = cmd[0]
      node_cmd = [prefix, cmd_type]
      cmd_args = [nm.screen().getSceenCmd(node)]
      cmd_args[len(cmd_args):] = node_cmd
      cmd_args.append(n.args)
      cmd_args[len(cmd_args):] = args
      rospy.loginfo("RUN: %s", ' '.join(cmd_args))
      subprocess.Popen(shlex.split(str(' '.join(cmd_args))))
    else:
      # start remote
      if launch_config.PackageName is None:
        raise StartException(''.join(["Can't run remote without a valid package name!"]))
      # setup environment
      env_command = ''
      if env_loader:
        rospy.logwarn("env_loader in machine tag currently not supported")
        raise nm.StartException("env_loader in machine tag currently not supported")
      if env:
        env_command = "env "+' '.join(["%s=%s"%(k,v) for (k, v) in env])
      
      startcmd = [env_command, nm.STARTER_SCRIPT, 
                  '--package', str(n.package),
                  '--node_type', str(n.type),
                  '--node_name', str(node)]
      if prefix:
        startcmd[len(startcmd):] = ['--prefix', prefix]

      startcmd[len(startcmd):] = n.args
      startcmd[len(startcmd):] = args
      rospy.loginfo("Run remote: %s", ' '.join(startcmd))
      (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd)

      if ok:
        stdin.close()
  #      stderr.close()
  #      stdout.close()
        error = stderr.read()
        if error:
          rospy.logwarn("ERROR while start '%s': %s", node, error)
          raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error])))
        output = stdout.read()
        if output:
          rospy.logdebug("STDOUT while start '%s': %s", node, output)
예제 #30
0
    def runNode(cls,
                node,
                launch_config,
                force2host=None,
                masteruri=None,
                auto_pw_request=False,
                user=None,
                pw=None):
        '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @param force2host: start the node on given host.
    @type force2host: L{str} 
    @param masteruri: force the masteruri.
    @type masteruri: L{str} 
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        #'print "RUN node", node, time.time()
        n = launch_config.getNode(node)
        if n is None:
            raise StartException(''.join(["Node '", node, "' not found!"]))

        env = list(n.env_args)
        prefix = n.launch_prefix if not n.launch_prefix is None else ''
        if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
            rospy.loginfo("SCREEN prefix removed before start!")
            prefix = ''
        args = [
            ''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])
        ]
        if not (n.cwd is None):
            args.append(''.join(['__cwd:=', n.cwd]))

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = launch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = launch_config.Roscfg.machines[n.machine_name]
            host = machine.address
            #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
# set the host to the given host
        if not force2host is None:
            host = force2host

        if masteruri is None:
            masteruri = nm.nameres().masteruri(n.machine_name)
        # set the ROS_MASTER_URI
        if masteruri is None:
            masteruri = nm.masteruri_from_ros()
            env.append(('ROS_MASTER_URI', masteruri))

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        # set the global parameter
        if not masteruri is None and not masteruri in launch_config.global_param_done:
            global_node_names = cls.getGlobalParams(launch_config.Roscfg)
            rospy.loginfo("Register global parameter:\n%s",
                          '\n'.join(global_node_names))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, global_node_names, [])
            launch_config.global_param_done.append(masteruri)

        # add params
        if not masteruri is None:
            nodens = ''.join([n.namespace, n.name, '/'])
            params = dict()
            for param, value in launch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in launch_config.Roscfg.clear_params:
                if cparam.startswith(nodens):
                    clear_params.append(param)
            rospy.loginfo("Register parameter:\n%s", '\n'.join(params))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, params, clear_params)
        #'print "RUN prepared", node, time.time()

        if nm.is_local(host):
            nm.screen().testScreen()
            try:
                cmd = roslib.packages.find_node(n.package, n.type)
            except (Exception, roslib.packages.ROSPkgException) as e:
                # multiple nodes, invalid package
                raise StartException(''.join(["Can't find resource: ",
                                              str(e)]))
            # handle diferent result types str or array of string
            import types
            if isinstance(cmd, types.StringTypes):
                cmd = [cmd]
            cmd_type = ''
            if cmd is None or len(cmd) == 0:
                raise StartException(' '.join([
                    n.type, 'in package [', n.package,
                    '] not found!\n\nThe package was created?\nIs the binary executable?\n'
                ]))
            if len(cmd) > 1:
                # Open selection for executables
                try:
                    from PySide import QtGui
                    item, result = QtGui.QInputDialog.getItem(
                        None, ' '.join(
                            ['Multiple executables', n.type, 'in', n.package]),
                        'Select an executable', cmd, 0, False)
                    if result:
                        #open the selected screen
                        cmd_type = item
                    else:
                        return
                except:
                    raise StartException(
                        'Multiple executables with same name in package found!'
                    )
            else:
                cmd_type = cmd[0]
            # determine the current working path, Default: the package of the node
            cwd = nm.get_ros_home()
            if not (n.cwd is None):
                if n.cwd == 'ROS_HOME':
                    cwd = nm.get_ros_home()
                elif n.cwd == 'node':
                    cwd = os.path.dirname(cmd_type)
#      else:
#        cwd = LaunchConfig.packageName(os.path.dirname(cmd_type))
            cls._prepareROSMaster(masteruri)
            node_cmd = [
                nm.RESPAWN_SCRIPT if n.respawn else '', prefix, cmd_type
            ]
            cmd_args = [nm.screen().getSceenCmd(node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(str(n.args))
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            if not masteruri is None:
                new_env = dict(os.environ)
                new_env['ROS_MASTER_URI'] = masteruri
                ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))),
                                      cwd=cwd,
                                      env=new_env)
            else:
                ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))),
                                      cwd=cwd)
            # wait for process to avoid 'defunct' processes
            thread = threading.Thread(target=ps.wait)
            thread.setDaemon(True)
            thread.start()
        else:
            #'print "RUN REMOTE", node, time.time()
            # start remote
            if launch_config.PackageName is None:
                raise StartException(''.join(
                    ["Can't run remote without a valid package name!"]))
            # thus the prefix parameters while the transfer are not separated
            if prefix:
                prefix = ''.join(['"', prefix, '"'])
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn(
                    "env_loader in machine tag currently not supported")
                raise StartException(
                    "env_loader in machine tag currently not supported")
            if env:
                env_command = "env " + ' '.join(
                    ["%s=%s" % (k, v) for (k, v) in env])

            startcmd = [
                env_command, nm.STARTER_SCRIPT, '--package',
                str(n.package), '--node_type',
                str(n.type), '--node_name',
                str(node), '--node_respawn true' if n.respawn else ''
            ]
            if not masteruri is None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]

            #rename the absolute paths in the args of the node
            node_args = []
            try:
                for a in n.args.split():
                    a_value, is_abs_path, found, package = cls._resolve_abs_paths(
                        a, host)
                    node_args.append(a_value)
                    if is_abs_path:
                        abs_paths.append(('ARGS', a, a_value))
                        if not found and package:
                            not_found_packages.append(package)

                startcmd[len(startcmd):] = node_args
                startcmd[len(startcmd):] = args
                rospy.loginfo("Run remote on %s: %s", host,
                              str(' '.join(startcmd)))
                #'print "RUN CALL", node, time.time()
                output, error, ok = nm.ssh().ssh_exec(host, startcmd, user, pw,
                                                      auto_pw_request)
                #'print "RUN CALLOK", node, time.time()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.runNode, (node, launch_config, force2host,
                                     masteruri, auto_pw_request))

            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", node, error)
                    raise StartException(
                        str(''.join(
                            ['The host "', host, '" reports:\n', error])))
                if output:
                    rospy.loginfo("STDOUT while start '%s': %s", node, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo(
                    "Absolute paths found while start:\n%s",
                    str('\n'.join([
                        ''.join([p, '\n  OLD: ', ov, '\n  NEW: ', nv])
                        for p, ov, nv in abs_paths
                    ])))

            if len(not_found_packages) > 0:
                packages = '\n'.join(not_found_packages)
                raise StartException(
                    str('\n'.join([
                        'Some absolute paths are not renamed because following packages are not found on remote host:',
                        packages
                    ])))
예제 #31
0
    def runNode(cls,
                node,
                launch_config,
                force2host=None,
                masteruri=None,
                auto_pw_request=False,
                user=None,
                pw=None,
                item=None):
        '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @param force2host: start the node on given host.
    @type force2host: L{str} 
    @param masteruri: force the masteruri.
    @type masteruri: L{str} 
    @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread
    @type auto_pw_request: bool
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        #'print "RUN node", node, time.time()
        n = launch_config.getNode(node)
        if n is None:
            raise StartException(''.join(["Node '", node, "' not found!"]))

        env = list(n.env_args)
        if n.respawn:
            # set the respawn environment variables
            respawn_params = cls._get_respawn_params(
                rospy.names.ns_join(n.namespace, n.name),
                launch_config.Roscfg.params)
            if respawn_params['max'] > 0:
                env.append(('RESPAWN_MAX', '%d' % respawn_params['max']))
            if respawn_params['min_runtime'] > 0:
                env.append(('RESPAWN_MIN_RUNTIME',
                            '%d' % respawn_params['min_runtime']))
            if respawn_params['delay'] > 0:
                env.append(('RESPAWN_DELAY', '%d' % respawn_params['delay']))
        prefix = n.launch_prefix if not n.launch_prefix is None else ''
        if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
            rospy.loginfo("SCREEN prefix removed before start!")
            prefix = ''
        args = [
            ''.join(['__ns:=', n.namespace.rstrip(rospy.names.SEP)]),
            ''.join(['__name:=', n.name])
        ]
        if not (n.cwd is None):
            args.append(''.join(['__cwd:=', n.cwd]))

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = launch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = launch_config.Roscfg.machines[n.machine_name]
            if not machine.address in ['localhost', '127.0.0.1']:
                host = machine.address
                if masteruri is None:
                    masteruri = nm.nameres().masteruri(n.machine_name)
            #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
# set the host to the given host
        if not force2host is None:
            host = force2host

        # set the ROS_MASTER_URI
        if masteruri is None:
            masteruri = masteruri_from_ros()
            env.append(('ROS_MASTER_URI', masteruri))

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        # set the global parameter
        if not masteruri is None and not masteruri in launch_config.global_param_done:
            global_node_names = cls.getGlobalParams(launch_config.Roscfg)
            rospy.loginfo(
                "Register global parameter:\n  %s", '\n  '.join(
                    "%s%s" % (str(v)[:80], '...' if len(str(v)) > 80 else '')
                    for v in global_node_names.values()))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, global_node_names, [], user, pw,
                    auto_pw_request)
            launch_config.global_param_done.append(masteruri)

        # add params
        if not masteruri is None:
            nodens = ''.join([n.namespace, n.name, rospy.names.SEP])
            params = dict()
            for param, value in launch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in launch_config.Roscfg.clear_params:
                if cparam.startswith(nodens):
                    clear_params.append(cparam)
            rospy.loginfo("Delete parameter:\n  %s", '\n  '.join(clear_params))
            rospy.loginfo(
                "Register parameter:\n  %s", '\n  '.join(
                    "%s%s" % (str(v)[:80], '...' if len(str(v)) > 80 else '')
                    for v in params.values()))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, params, clear_params, user, pw, auto_pw_request)
        #'print "RUN prepared", node, time.time()

        if nm.is_local(host):
            nm.screen().testScreen()
            if item:
                cmd_type = item
            else:
                try:
                    cmd = roslib.packages.find_node(n.package, n.type)
                except (Exception, roslib.packages.ROSPkgException) as e:
                    # multiple nodes, invalid package
                    raise StartException(''.join(
                        ["Can't find resource: ",
                         str(e)]))
                # handle diferent result types str or array of string
                if isinstance(cmd, types.StringTypes):
                    cmd = [cmd]
                cmd_type = ''
                if cmd is None or len(cmd) == 0:
                    raise StartException(' '.join([
                        n.type, 'in package [', n.package,
                        '] not found!\n\nThe package was created?\nIs the binary executable?\n'
                    ]))
                if len(cmd) > 1:
                    if auto_pw_request:
                        # Open selection for executables, only if the method is called from the main GUI thread
                        try:
                            from python_qt_binding import QtGui
                            item, result = QtGui.QInputDialog.getItem(
                                None, ' '.join([
                                    'Multiple executables', n.type, 'in',
                                    n.package
                                ]), 'Select an executable', cmd, 0, False)
                            if result:
                                #open the selected screen
                                cmd_type = item
                            else:
                                return
                        except:
                            raise StartException(
                                'Multiple executables with same name in package found!'
                            )
                    else:
                        err = BinarySelectionRequest(cmd,
                                                     'Multiple executables')
                        raise nm.InteractionNeededError(
                            err, cls.runNode,
                            (node, launch_config, force2host, masteruri,
                             auto_pw_request, user, pw))
                else:
                    cmd_type = cmd[0]
            # determine the current working path, Default: the package of the node
            cwd = get_ros_home()
            if not (n.cwd is None):
                if n.cwd == 'ROS_HOME':
                    cwd = get_ros_home()
                elif n.cwd == 'node':
                    cwd = os.path.dirname(cmd_type)
            cls._prepareROSMaster(masteruri)
            node_cmd = [
                nm.settings().respawn_script if n.respawn else '', prefix,
                cmd_type
            ]
            cmd_args = [nm.screen().getSceenCmd(node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(str(n.args))
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            new_env = dict(os.environ)
            new_env['ROS_MASTER_URI'] = masteruri
            # add the namespace environment parameter to handle some cases, e.g. rqt_cpp plugins
            if n.namespace:
                new_env['ROS_NAMESPACE'] = n.namespace
            for k, v in env:
                new_env[k] = v
            SupervisedPopen(shlex.split(str(' '.join(cmd_args))),
                            cwd=cwd,
                            env=new_env,
                            id="Run node",
                            description="Run node [%s]%s" %
                            (str(n.package), str(n.type)))
        else:
            #'print "RUN REMOTE", node, time.time()
            # start remote
            if launch_config.PackageName is None:
                raise StartException(''.join(
                    ["Can't run remote without a valid package name!"]))
            # thus the prefix parameters while the transfer are not separated
            if prefix:
                prefix = ''.join(['"', prefix, '"'])
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn(
                    "env_loader in machine tag currently not supported")
                raise StartException(
                    "env_loader in machine tag currently not supported")
            if env:
                new_env = dict()
                try:
                    for (k, v) in env:
                        v_value, is_abs_path, found, package = cls._resolve_abs_paths(
                            v, host, user, pw, auto_pw_request)
                        new_env[k] = v_value
                        if is_abs_path:
                            abs_paths.append(('ENV', "%s=%s" % (k, v),
                                              "%s=%s" % (k, v_value)))
                            if not found and package:
                                not_found_packages.append(package)
                    env_command = "env " + ' '.join(
                        ["%s=%s" % (k, v) for (k, v) in new_env.items()])
                except nm.AuthenticationRequest as e:
                    raise nm.InteractionNeededError(
                        e, cls.runNode, (node, launch_config, force2host,
                                         masteruri, auto_pw_request))

            startcmd = [
                env_command,
                nm.settings().start_remote_script, '--package',
                str(n.package), '--node_type',
                str(n.type), '--node_name',
                str(node), '--node_respawn true' if n.respawn else ''
            ]
            if not masteruri is None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]

            #rename the absolute paths in the args of the node
            node_args = []
            try:
                for a in n.args.split():
                    a_value, is_abs_path, found, package = cls._resolve_abs_paths(
                        a, host, user, pw, auto_pw_request)
                    node_args.append(a_value)
                    if is_abs_path:
                        abs_paths.append(('ARGS', a, a_value))
                        if not found and package:
                            not_found_packages.append(package)

                startcmd[len(startcmd):] = node_args
                startcmd[len(startcmd):] = args
                rospy.loginfo("Run remote on %s: %s", host,
                              str(' '.join(startcmd)))
                #'print "RUN CALL", node, time.time()
                _, stdout, stderr, ok = nm.ssh().ssh_exec(host,
                                                          startcmd,
                                                          user,
                                                          pw,
                                                          auto_pw_request,
                                                          close_stdin=True)
                output = stdout.read()
                error = stderr.read()
                stdout.close()
                stderr.close()
                #'print "RUN CALLOK", node, time.time()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.runNode, (node, launch_config, force2host,
                                     masteruri, auto_pw_request))

            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", node, error)
                    raise StartException(
                        str(''.join(
                            ['The host "', host, '" reports:\n', error])))
                if output:
                    rospy.loginfo("STDOUT while start '%s': %s", node, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo(
                    "Absolute paths found while start:\n%s",
                    str('\n'.join([
                        ''.join([p, '\n  OLD: ', ov, '\n  NEW: ', nv])
                        for p, ov, nv in abs_paths
                    ])))

            if len(not_found_packages) > 0:
                packages = '\n'.join(not_found_packages)
                raise StartException(
                    str('\n'.join([
                        'Some absolute paths are not renamed because following packages are not found on remote host:',
                        packages
                    ])))
예제 #32
0
    def runNode(cls, node, launch_config):
        '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        n = launch_config.getNode(node)
        if n is None:
            raise StartException(''.join(["Node '", node, "' not found!"]))

        env = list(n.env_args)
        prefix = n.launch_prefix if not n.launch_prefix is None else ''
        # thus the parameters while the transfer are not separated
        if prefix:
            prefix = ''.join(['"', prefix, '"'])
        args = [
            ''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])
        ]
        if not (n.cwd is None):
            args.append(''.join(['__cwd:=', n.cwd]))

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = launch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = launch_config.Roscfg.machines[n.machine_name]
            host = machine.address
            #TODO: env-loader support?


#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader

        masteruri = nm.nameres().getUri(host=host)
        # set the ROS_MASTER_URI
        if masteruri is None:
            env.append(('ROS_MASTER_URI', nm.masteruri_from_ros()))

        # set the global parameter
        if not masteruri is None and not masteruri in launch_config.global_param_done:
            global_node_names = cls.getGlobalParams(launch_config.Roscfg)
            rospy.loginfo("Register global parameter:\n%s",
                          '\n'.join(global_node_names))
            cls._load_parameters(masteruri, global_node_names, [])
            launch_config.global_param_done.append(masteruri)

        # add params
        if not masteruri is None:
            nodens = ''.join([n.namespace, n.name, '/'])
            params = dict()
            for param, value in launch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in launch_config.Roscfg.clear_params:
                if cparam.startswith(nodens):
                    clear_params.append(param)
            rospy.loginfo("Register parameter:\n%s", '\n'.join(params))
            cls._load_parameters(masteruri, params, clear_params)
        if nm.is_local(host):
            nm.screen().testScreen()
            try:
                cmd = roslib.packages.find_node(n.package, n.type)
            except (Exception, roslib.packages.ROSPkgException) as e:
                # multiple nodes, invalid package
                raise StartException(''.join(["Can't find resource: ",
                                              str(e)]))
            # handle diferent result types str or array of string
            import types
            if isinstance(cmd, types.StringTypes):
                cmd = [cmd]
            cmd_type = ''
            if cmd is None or len(cmd) == 0:
                raise nm.StartException(' '.join([
                    n.type, 'in package [', n.package,
                    '] not found!\n\nThe package was created?\nIs the binary executable?\n'
                ]))
            if len(cmd) > 1:
                # Open selection for executables
                try:
                    from PySide import QtGui
                    item, result = QtGui.QInputDialog.getItem(
                        None, ' '.join(
                            ['Multiple executables', n.type, 'in', n.package]),
                        'Select an executable', cmd, 0, False)
                    if result:
                        #open the selected screen
                        cmd_type = item
                    else:
                        return
                except:
                    raise nm.StartException(
                        'Multiple executables with same name in package found!'
                    )
            else:
                cmd_type = cmd[0]
            node_cmd = [prefix, cmd_type]
            cmd_args = [nm.screen().getSceenCmd(node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(n.args)
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            subprocess.Popen(shlex.split(str(' '.join(cmd_args))))
        else:
            # start remote
            if launch_config.PackageName is None:
                raise StartException(''.join(
                    ["Can't run remote without a valid package name!"]))
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn(
                    "env_loader in machine tag currently not supported")
                raise nm.StartException(
                    "env_loader in machine tag currently not supported")
            if env:
                env_command = "env " + ' '.join(
                    ["%s=%s" % (k, v) for (k, v) in env])

            startcmd = [
                env_command, nm.STARTER_SCRIPT, '--package',
                str(n.package), '--node_type',
                str(n.type), '--node_name',
                str(node)
            ]
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]

            startcmd[len(startcmd):] = n.args
            startcmd[len(startcmd):] = args
            rospy.loginfo("Run remote: %s", ' '.join(startcmd))
            (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd)

            if ok:
                stdin.close()
                #      stderr.close()
                #      stdout.close()
                error = stderr.read()
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", node, error)
                    raise nm.StartException(
                        str(''.join(
                            ['The host "', host, '" reports:\n', error])))
                output = stdout.read()
                if output:
                    rospy.logdebug("STDOUT while start '%s': %s", node, output)
예제 #33
0
  def runNode(cls, node, launch_config, force2host=None, masteruri=None):
    '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @param force2host: start the node on given host.
    @type force2host: L{str} 
    @param masteruri: force the masteruri.
    @type masteruri: L{str} 
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
    n = launch_config.getNode(node)
    if n is None:
      raise StartException(''.join(["Node '", node, "' not found!"]))
    
    env = list(n.env_args)
    prefix = n.launch_prefix if not n.launch_prefix is None else ''
    if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
      rospy.loginfo("SCREEN prefix removed before start!")
      prefix = ''
    args = [''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])]
    if not (n.cwd is None):
      args.append(''.join(['__cwd:=', n.cwd]))
    
    # add remaps
    for remap in n.remap_args:
      args.append(''.join([remap[0], ':=', remap[1]]))

    # get host of the node
    host = launch_config.hostname
    env_loader = ''
    if n.machine_name:
      machine = launch_config.Roscfg.machines[n.machine_name]
      host = machine.address
      #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
    # set the host to the given host
    if not force2host is None:
      host = force2host

    if masteruri is None:
      masteruri = nm.nameres().masteruri(n.machine_name)
    # set the ROS_MASTER_URI
    if masteruri is None:
      masteruri = nm.masteruri_from_ros()
      env.append(('ROS_MASTER_URI', masteruri))

    abs_paths = list() # tuples of (parameter name, old value, new value)
    not_found_packages = list() # package names
    # set the global parameter
    if not masteruri is None and not masteruri in launch_config.global_param_done:
      global_node_names = cls.getGlobalParams(launch_config.Roscfg)
      rospy.loginfo("Register global parameter:\n%s", '\n'.join(global_node_names))
      abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(masteruri, global_node_names, [])
      launch_config.global_param_done.append(masteruri)

    # add params
    if not masteruri is None:
      nodens = ''.join([n.namespace, n.name, '/'])
      params = dict()
      for param, value in launch_config.Roscfg.params.items():
        if param.startswith(nodens):
          params[param] = value
      clear_params = []
      for cparam in launch_config.Roscfg.clear_params:
        if cparam.startswith(nodens):
          clear_params.append(param)
      rospy.loginfo("Register parameter:\n%s", '\n'.join(params))
      abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(masteruri, params, clear_params)
    if nm.is_local(host): 
      nm.screen().testScreen()
      try:
        cmd = roslib.packages.find_node(n.package, n.type)
      except (Exception, roslib.packages.ROSPkgException) as e:
        # multiple nodes, invalid package
        raise StartException(''.join(["Can't find resource: ", str(e)]))
      # handle diferent result types str or array of string
      import types
      if isinstance(cmd, types.StringTypes):
        cmd = [cmd]
      cmd_type = ''
      if cmd is None or len(cmd) == 0:
        raise nm.StartException(' '.join([n.type, 'in package [', n.package, '] not found!\n\nThe package was created?\nIs the binary executable?\n']))
      if len(cmd) > 1:
        # Open selection for executables
        try:
          from PySide import QtGui
          item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', n.type, 'in', n.package]),
                                            'Select an executable',
                                            cmd, 0, False)
          if result:
            #open the selected screen
            cmd_type = item
          else:
            return
        except:
          raise nm.StartException('Multiple executables with same name in package found!')
      else:
        cmd_type = cmd[0]
      # determine the current working path, Default: the package of the node
      cwd = nm.get_ros_home()
      if not (n.cwd is None):
        if n.cwd == 'ROS_HOME':
          cwd = nm.get_ros_home()
        elif n.cwd == 'node':
          cwd = os.path.dirname(cmd_type)
#      else:
#        cwd = LaunchConfig.packageName(os.path.dirname(cmd_type))
      cls._prepareROSMaster(masteruri)
      node_cmd = [nm.RESPAWN_SCRIPT if n.respawn else '', prefix, cmd_type]
      cmd_args = [nm.screen().getSceenCmd(node)]
      cmd_args[len(cmd_args):] = node_cmd
      cmd_args.append(str(n.args))
      cmd_args[len(cmd_args):] = args
      rospy.loginfo("RUN: %s", ' '.join(cmd_args))
      if not masteruri is None:
        new_env=dict(os.environ)
        new_env['ROS_MASTER_URI'] = masteruri
        ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd, env=new_env)
      else:
        ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))), cwd=cwd)
      # wait for process to avoid 'defunct' processes
      thread = threading.Thread(target=ps.wait)
      thread.setDaemon(True)
      thread.start()
    else:
      # start remote
      if launch_config.PackageName is None:
        raise StartException(''.join(["Can't run remote without a valid package name!"]))
      # thus the prefix parameters while the transfer are not separated
      if prefix:
        prefix = ''.join(['"', prefix, '"'])
      # setup environment
      env_command = ''
      if env_loader:
        rospy.logwarn("env_loader in machine tag currently not supported")
        raise nm.StartException("env_loader in machine tag currently not supported")
      if env:
        env_command = "env "+' '.join(["%s=%s"%(k,v) for (k, v) in env])
      
      startcmd = [env_command, nm.STARTER_SCRIPT, 
                  '--package', str(n.package),
                  '--node_type', str(n.type),
                  '--node_name', str(node),
                  '--node_respawn true' if n.respawn else '']
      if not masteruri is None:
        startcmd.append('--masteruri')
        startcmd.append(masteruri)
      if prefix:
        startcmd[len(startcmd):] = ['--prefix', prefix]
      
      #rename the absolute paths in the args of the node
      node_args = []
      for a in n.args.split():
        a_value, is_abs_path, found, package = cls._resolve_abs_paths(a, host)
        node_args.append(a_value)
        if is_abs_path:
          abs_paths.append(('ARGS', a, a_value))
          if not found and package:
            not_found_packages.append(package)

      startcmd[len(startcmd):] = node_args
      startcmd[len(startcmd):] = args
      rospy.loginfo("Run remote on %s: %s", host, str(' '.join(startcmd)))
      (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd)

      if ok:
        stdin.close()
  #      stderr.close()
  #      stdout.close()
        error = stderr.read()
        if error:
          rospy.logwarn("ERROR while start '%s': %s", node, error)
          raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error])))
        output = stdout.read()
        if output:
          rospy.loginfo("STDOUT while start '%s': %s", node, output)
      # inform about absolute paths in parameter value
      if len(abs_paths) > 0:
        rospy.loginfo("Absolute paths found while start:\n%s", str('\n'.join([''.join([p, '\n  OLD: ', ov, '\n  NEW: ', nv]) for p, ov, nv in abs_paths])))

      if len(not_found_packages) > 0:
        packages = '\n'.join(not_found_packages)
        raise nm.StartException(str('\n'.join(['Some absolute paths are not renamed because following packages are not found on remote host:', packages])))
예제 #34
0
 def on_save_profile(self, masteruri='', path=None):
     '''
     Saves the current environment to a node manager profile.
     :param path: the pach the file to save
     :type path: str
     :param masteruri: If not empty, save the profile only for given master
     :type masteruri: str
     '''
     try:
         if path is None:
             path = self.get_profile_file()
             if path is None:
                 return
         rospy.loginfo("Save profile %s" % path)
         import yaml
         content = {}
         for muri, master in self._main_window.masters.items():
             if not masteruri or masteruri == muri:
                 running_nodes = master.getRunningNodesIfLocal()
                 configs = {}
                 md_param = {}
                 ms_param = {}
                 zc_param = {}
                 smuri = muri
                 addr = nm.nameres().address(smuri)
                 hostname = get_hostname(smuri)
                 mastername = ''
                 if nm.is_local(addr):
                     smuri = smuri.replace(hostname, '$LOCAL$')
                     addr = '$LOCAL$'
                 else:
                     mastername = nm.nameres().mastername(
                         smuri,
                         nm.nameres().address(smuri))
                 for node_name in running_nodes.keys():
                     node_items = master.getNode(node_name)
                     for node in node_items:
                         if node.is_running(
                         ) and node.launched_cfg is not None:  # node.has_launch_cfgs(node.cfgs):
                             cfg = node.launched_cfg
                             if isinstance(node.launched_cfg,
                                           (str, unicode)):
                                 # it is default config
                                 cfg = node.launched_cfg.replace(
                                     "/%s" % hostname,
                                     '/$LOCAL$').rstrip('/run')
                             else:
                                 # it is a loaded launch file, get the filename
                                 cfg = to_url(node.launched_cfg.Filename)
                             if cfg not in configs:
                                 configs[cfg] = {'nodes': []}
                             configs[cfg]['nodes'].append(node_name)
                         elif node_name.endswith('master_discovery'):
                             md_param = get_rosparam(
                                 'master_discovery', muri)
                         elif node_name.endswith('master_sync'):
                             ms_param = get_rosparam('master_sync', muri)
                         elif node_name.endswith('zeroconf'):
                             zc_param = get_rosparam('zeroconf', muri)
                         elif node_name.endswith('default_cfg'):
                             # store parameter for default configuration
                             nn = node_name.replace("/%s" % hostname,
                                                    '/$LOCAL$')
                             if nn not in configs:
                                 configs[nn] = {'nodes': []}
                             configs[nn]['params'] = get_rosparam(
                                 node_name, muri)
                             configs[nn]['default'] = True
                 # store arguments for launchfiles
                 for a, b in master.launchfiles.items():
                     resolved_a = to_url(a)
                     if resolved_a not in configs:
                         if resolved_a.endswith('default_cfg/run'):
                             pass
                         else:
                             configs[resolved_a] = {}
                             configs[resolved_a]['default'] = False
                     configs[resolved_a]['argv'] = b.argv
                 # fill the configuration content for yaml as dictionary
                 content[smuri] = {
                     'mastername': mastername,
                     'address': addr,
                     'configs': configs
                 }
                 if md_param:
                     content[smuri]['master_discovery'] = md_param
                 if ms_param:
                     content[smuri]['master_sync'] = ms_param
                 if zc_param:
                     content[smuri]['zeroconf'] = zc_param
         text = yaml.dump(content, default_flow_style=False)
         with open(path, 'w+') as f:
             f.write(text)
     except Exception as e:
         import traceback
         print traceback.format_exc(3)
         WarningMessageBox(QMessageBox.Warning, "Save profile Error",
                           'Error while save profile', str(e)).exec_()
예제 #35
0
 def on_load_profile_file(self, path):
     '''
     Load the profile file.
     :param path: the path of the profile file.
     :type path: str
     '''
     rospy.loginfo("Load profile %s" % path)
     self.progressBar.setValue(0)
     self.setVisible(True)
     self.setWindowTitle("%s profile started" %
                         os.path.basename(path).rstrip('.nmprofile'))
     hasstart = False
     if path:
         try:
             import yaml
             with open(path, 'r') as f:
                 # print yaml.load(f.read())
                 content = yaml.load(f.read())
                 if not isinstance(content, dict):
                     raise Exception("Mailformed profile: %s" %
                                     os.path.basename(path))
                 for muri, master_dict in content.items():
                     local_hostname = get_hostname(
                         self._main_window.getMasteruri())
                     rmuri = muri.replace('$LOCAL$', local_hostname)
                     master = self._main_window.getMaster(rmuri)
                     running_nodes = master.getRunningNodesIfLocal()
                     usr = None
                     self._current_profile[rmuri] = set()
                     if 'user' in master_dict:
                         usr = master_dict['user']
                     if master_dict['mastername'] and master_dict[
                             'mastername']:
                         nm.nameres().add_master_entry(
                             master.masteruri, master_dict['mastername'],
                             master_dict['address'])
                     hostname = master_dict['address'].replace(
                         '$LOCAL$', local_hostname)
                     if 'master_discovery' in master_dict:
                         self._start_node_from_profile(
                             master,
                             hostname,
                             'master_discovery_fkie',
                             'master_discovery',
                             usr,
                             cfg=master_dict['master_discovery'])
                         self._current_profile[rmuri].add(
                             '/master_discovery')
                     if 'master_sync' in master_dict:
                         self._start_node_from_profile(
                             master,
                             hostname,
                             'master_sync_fkie',
                             'master_sync',
                             usr,
                             cfg=master_dict['master_sync'])
                         self._current_profile[rmuri].add('/master_sync')
                     if 'zeroconf' in master_dict:
                         self._start_node_from_profile(
                             master,
                             hostname,
                             'master_discovery_fkie',
                             'zeroconf',
                             usr,
                             cfg=master_dict['zeroconf'])
                         self._current_profile[rmuri].add('/zeroconf')
                     try:
                         do_start = []
                         do_not_stop = {
                             '/rosout',
                             rospy.get_name(), '/node_manager',
                             '/master_discovery', '/master_sync',
                             '*default_cfg', '/zeroconf'
                         }
                         configs = master_dict['configs']
                         conf_set = set()
                         for cfg_name, cmdict in configs.items():
                             cfg_name = cfg_name.replace(
                                 '$LOCAL$', local_hostname)
                             if cfg_name.startswith("pkg://"):
                                 cfg_name = os.path.abspath(
                                     resolve_url(cfg_name))
                             conf_set.add(cfg_name)
                             reload_launch = True
                             argv = []
                             is_default = False
                             if 'default' in cmdict:
                                 if cmdict['default']:
                                     # it is a default configuration, test for load or not
                                     is_default = True
                                     if 'argv_used' in cmdict['params']:
                                         argv = cmdict['params'][
                                             'argv_used']
                                     if cfg_name in master.default_cfgs:
                                         reload_launch = False
                                         if argv:
                                             params = get_rosparam(
                                                 cfg_name, rmuri)
                                             if 'argv_used' in params:
                                                 reload_launch = set(
                                                     params['argv_used']
                                                 ) != set(argv)
                                     if reload_launch:
                                         self._main_window.on_load_launch_as_default_bypkg(
                                             cmdict['params']['package'],
                                             cmdict['params']
                                             ['launch_file'], master, argv,
                                             local_hostname)
                                     else:
                                         do_not_stop.add(cfg_name)
                             elif 'argv' in cmdict:
                                 if 'argv' in cmdict:
                                     argv = cmdict['argv']
                                 # do we need to load to load/reload launch file
                                 if cfg_name in master.launchfiles:
                                     reload_launch = set(
                                         master.launchfiles[cfg_name].argv
                                     ) != set(argv)
                             if reload_launch:
                                 self._main_window.launch_dock.load_file(
                                     cfg_name, argv, master.masteruri)
                             if 'nodes' in cmdict:
                                 self._current_profile[rmuri].update(
                                     cmdict['nodes'])
                                 force_start = True
                                 cfg = cfg_name if not is_default else roslib.names.ns_join(
                                     cfg_name, 'run')
                                 if not reload_launch:
                                     force_start = False
                                     do_not_stop.update(set(
                                         cmdict['nodes']))
                                     do_start.append(
                                         (reload_launch, cfg,
                                          cmdict['nodes'], force_start))
                                 else:
                                     do_start.append(
                                         (reload_launch, cfg,
                                          cmdict['nodes'], force_start))
                         # close unused configurations
                         for lfile in set(
                                 master.launchfiles.keys()) - conf_set:
                             master._close_cfg(lfile)
                         master.stop_nodes_by_name(running_nodes.keys(),
                                                   True, do_not_stop)
                         for reload_launch, cfg, nodes, force_start in do_start:
                             if nodes:
                                 hasstart = True
                             if reload_launch:
                                 master.start_nodes_after_load_cfg(
                                     cfg.rstrip('/run'), list(nodes),
                                     force_start)
                             else:
                                 master.start_nodes_by_name(
                                     list(nodes), cfg, force_start)
                     except Exception as ml:
                         import traceback
                         print traceback.format_exc(1)
                         rospy.logwarn(
                             "Can not load launch file for %s: %s" %
                             (muri, ml))
         except Exception as e:
             import traceback
             print traceback.format_exc(1)
             WarningMessageBox(QMessageBox.Warning, "Load profile error",
                               'Error while load profile', str(e)).exec_()
         if not hasstart:
             self.update_progress()
         else:
             QTimer.singleShot(1000, self.update_progress)
 def on_load_profile_file(self, path):
     '''
     Load the profile file.
     :param path: the path of the profile file.
     :type path: str
     '''
     rospy.loginfo("Load profile %s" % path)
     self.progressBar.setValue(0)
     self.setVisible(True)
     self.setWindowTitle("%s profile started" % os.path.basename(path).rstrip('.nmprofile'))
     hasstart = False
     if path:
         try:
             import yaml
             with open(path, 'r') as f:
                 # print yaml.load(f.read())
                 content = yaml.load(f.read())
                 if not isinstance(content, dict):
                     raise Exception("Mailformed profile: %s" % os.path.basename(path))
                 for muri, master_dict in content.items():
                     local_hostname = get_hostname(self._main_window.getMasteruri())
                     rmuri = muri.replace('$LOCAL$', local_hostname)
                     master = self._main_window.getMaster(rmuri)
                     running_nodes = master.getRunningNodesIfLocal()
                     usr = None
                     self._current_profile[rmuri] = set()
                     if 'user' in master_dict:
                         usr = master_dict['user']
                     if master_dict['mastername'] and master_dict['mastername']:
                         nm.nameres().add_master_entry(master.masteruri, master_dict['mastername'], master_dict['address'])
                     hostname = master_dict['address'].replace('$LOCAL$', local_hostname)
                     if 'master_discovery' in master_dict:
                         self._start_node_from_profile(master, hostname, 'master_discovery_fkie', 'master_discovery', usr, cfg=master_dict['master_discovery'])
                         self._current_profile[rmuri].add('/master_discovery')
                     if 'master_sync' in master_dict:
                         self._start_node_from_profile(master, hostname, 'master_sync_fkie', 'master_sync', usr, cfg=master_dict['master_sync'])
                         self._current_profile[rmuri].add('/master_sync')
                     if 'zeroconf' in master_dict:
                         self._start_node_from_profile(master, hostname, 'master_discovery_fkie', 'zeroconf', usr, cfg=master_dict['zeroconf'])
                         self._current_profile[rmuri].add('/zeroconf')
                     try:
                         do_start = []
                         do_not_stop = {'/rosout', rospy.get_name(), '/node_manager', '/master_discovery', '/master_sync', '*default_cfg', '/zeroconf'}
                         configs = master_dict['configs']
                         conf_set = set()
                         for cfg_name, cmdict in configs.items():
                             cfg_name = cfg_name.replace('$LOCAL$', local_hostname)
                             if cfg_name.startswith("pkg://"):
                                 cfg_name = os.path.abspath(resolve_url(cfg_name))
                             conf_set.add(cfg_name)
                             reload_launch = True
                             argv = []
                             is_default = False
                             if 'default' in cmdict:
                                 if cmdict['default']:
                                     # it is a default configuration, test for load or not
                                     is_default = True
                                     if 'argv_used' in cmdict['params']:
                                         argv = cmdict['params']['argv_used']
                                     if cfg_name in master.default_cfgs:
                                         reload_launch = False
                                         if argv:
                                             params = get_rosparam(cfg_name, rmuri)
                                             if 'argv_used' in params:
                                                 reload_launch = set(params['argv_used']) != set(argv)
                                     if reload_launch:
                                         self._main_window.on_load_launch_as_default_bypkg(cmdict['params']['package'], cmdict['params']['launch_file'], master, argv, local_hostname)
                                     else:
                                         do_not_stop.add(cfg_name)
                             elif 'argv' in cmdict:
                                 if 'argv' in cmdict:
                                     argv = cmdict['argv']
                                 # do we need to load to load/reload launch file
                                 if cfg_name in master.launchfiles:
                                     reload_launch = set(master.launchfiles[cfg_name].argv) != set(argv)
                             if reload_launch:
                                 self._main_window.launch_dock.load_file(cfg_name, argv, master.masteruri)
                             if 'nodes' in cmdict:
                                 self._current_profile[rmuri].update(cmdict['nodes'])
                                 force_start = True
                                 cfg = cfg_name if not is_default else roslib.names.ns_join(cfg_name, 'run')
                                 if not reload_launch:
                                     force_start = False
                                     do_not_stop.update(set(cmdict['nodes']))
                                     do_start.append((reload_launch, cfg, cmdict['nodes'], force_start))
                                 else:
                                     do_start.append((reload_launch, cfg, cmdict['nodes'], force_start))
                         # close unused configurations
                         for lfile in set(master.launchfiles.keys()) - conf_set:
                             master._close_cfg(lfile)
                         master.stop_nodes_by_name(running_nodes.keys(), True, do_not_stop)
                         for reload_launch, cfg, nodes, force_start in do_start:
                             if nodes:
                                 hasstart = True
                             if reload_launch:
                                 master.start_nodes_after_load_cfg(cfg.rstrip('/run'), list(nodes), force_start)
                             else:
                                 master.start_nodes_by_name(list(nodes), cfg, force_start)
                     except Exception as ml:
                         import traceback
                         print utf8(traceback.format_exc(1))
                         rospy.logwarn("Can not load launch file for %s: %s" % (muri, utf8(ml)))
         except Exception as e:
             import traceback
             print traceback.format_exc(1)
             MessageBox.warning(self, "Load profile error",
                                'Error while load profile',
                                utf8(e))
         if not hasstart:
             self.update_progress()
         else:
             QTimer.singleShot(1000, self.update_progress)
    def runNode(cls, runcfg):
        '''
        Start the node with given name from the given configuration.
        @param runcfg: the configuration containing the start parameter
        @type runcfg: AdvRunCfg
        @raise StartException: if the screen is not available on host.
        @raise Exception: on errors while resolving host
        @see: L{node_manager_fkie.is_local()}
        '''
        # 'print "RUN node", node, time.time()
        n = runcfg.roslaunch_config.getNode(runcfg.node)
        if n is None:
            raise StartException(''.join(["Node '", runcfg.node, "' not found!"]))

        env = list(n.env_args)
        # set logging options
        if runcfg.logging is not None:
            if not runcfg.logging.is_default('console_format'):
                env.append(('ROSCONSOLE_FORMAT', '%s' % runcfg.logging.console_format))
        if n.respawn:
            # set the respawn environment variables
            respawn_params = cls._get_respawn_params(rospy.names.ns_join(n.namespace, n.name), runcfg.roslaunch_config.Roscfg.params)
            if respawn_params['max'] > 0:
                env.append(('RESPAWN_MAX', '%d' % respawn_params['max']))
            if respawn_params['min_runtime'] > 0:
                env.append(('RESPAWN_MIN_RUNTIME', '%d' % respawn_params['min_runtime']))
            if respawn_params['delay'] > 0:
                env.append(('RESPAWN_DELAY', '%d' % respawn_params['delay']))
        prefix = n.launch_prefix if n.launch_prefix is not None else ''
        if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
            rospy.loginfo("SCREEN prefix removed before start!")
            prefix = ''
        args = ['__ns:=%s' % n.namespace.rstrip(rospy.names.SEP), '__name:=%s' % n.name]
        if n.cwd is not None:
            args.append('__cwd:=%s' % n.cwd)

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = runcfg.roslaunch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = runcfg.roslaunch_config.Roscfg.machines[n.machine_name]
            if machine.address not in ['localhost', '127.0.0.1']:
                host = machine.address
                if runcfg.masteruri is None:
                    runcfg.masteruri = nm.nameres().masteruri(n.machine_name)
            # TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
        # set the host to the given host
        if runcfg.force2host is not None:
            host = runcfg.force2host

        # set the ROS_MASTER_URI
        if runcfg.masteruri is None:
            runcfg.masteruri = masteruri_from_ros()
            env.append(('ROS_MASTER_URI', runcfg.masteruri))
            ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri)
            if ros_hostname:
                env.append(('ROS_HOSTNAME', ros_hostname))

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        # set the global parameter
        if runcfg.masteruri is not None and runcfg.masteruri not in runcfg.roslaunch_config.global_param_done:
            global_node_names = cls.getGlobalParams(runcfg.roslaunch_config.Roscfg)
            rospy.loginfo("Register global parameter:\n  %s", '\n  '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in global_node_names.values()))
            abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, global_node_names, [], runcfg.user, runcfg.pw, runcfg.auto_pw_request)
            runcfg.roslaunch_config.global_param_done.append(runcfg.masteruri)

        # add params
        if runcfg.masteruri is not None:
            nodens = ''.join([n.namespace, n.name, rospy.names.SEP])
            params = dict()
            for param, value in runcfg.roslaunch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in runcfg.roslaunch_config.Roscfg.clear_params:
                if cparam.startswith(nodens):
                    clear_params.append(cparam)
            rospy.loginfo("Delete parameter:\n  %s", '\n  '.join(clear_params))
            rospy.loginfo("Register parameter:\n  %s", '\n  '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in params.values()))
            abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, params, clear_params, runcfg.user, runcfg.pw, runcfg.auto_pw_request)
        # 'print "RUN prepared", node, time.time()

        if nm.is_local(host, wait=True):
            nm.screen().testScreen()
            if runcfg.executable:
                cmd_type = runcfg.executable
            else:
                try:
                    cmd = roslib.packages.find_node(n.package, n.type)
                except (Exception, roslib.packages.ROSPkgException) as starterr:
                    # multiple nodes, invalid package
                    raise StartException("Can't find resource: %s" % starterr)
                # handle diferent result types str or array of string
                if isinstance(cmd, types.StringTypes):
                    cmd = [cmd]
                cmd_type = ''
                if cmd is None or len(cmd) == 0:
                    raise StartException("%s in package [%s] not found!\n\nThe package "
                                         "was created?\nIs the binary executable?\n" % (n.type, n.package))
                if len(cmd) > 1:
                    if runcfg.auto_pw_request:
                        # Open selection for executables, only if the method is called from the main GUI thread
                        try:
                            try:
                                from python_qt_binding.QtGui import QInputDialog
                            except:
                                from python_qt_binding.QtWidgets import QInputDialog
                            item, result = QInputDialog.getItem(None, 'Multiple executables %s in %s' % (n.type, n.package),
                                                                'Select an executable',
                                                                cmd, 0, False)
                            if result:
                                # open the selected screen
                                cmd_type = item
                            else:
                                return
                        except:
                            raise StartException('Multiple executables with same name in package found!')
                    else:
                        err = BinarySelectionRequest(cmd, 'Multiple executables')
                        raise nm.InteractionNeededError(err, cls.runNode,
                                                        (runcfg,))
                else:
                    cmd_type = cmd[0]
            # determine the current working path, Default: the package of the node
            cwd = get_ros_home()
            if not (n.cwd is None):
                if n.cwd == 'ROS_HOME':
                    cwd = get_ros_home()
                elif n.cwd == 'node':
                    cwd = os.path.dirname(cmd_type)
            cls._prepareROSMaster(runcfg.masteruri)
            node_cmd = [nm.settings().respawn_script if n.respawn else '', prefix, cmd_type]
            cmd_args = [nm.screen().getSceenCmd(runcfg.node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(utf8(n.args))
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            new_env = dict(os.environ)
            new_env['ROS_MASTER_URI'] = runcfg.masteruri
            ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri)
            if ros_hostname:
                new_env['ROS_HOSTNAME'] = ros_hostname
            # add the namespace environment parameter to handle some cases,
            # e.g. rqt_cpp plugins
            if n.namespace:
                new_env['ROS_NAMESPACE'] = n.namespace
            # set logging options
            if runcfg.logging is not None:
                if not runcfg.logging.is_default('loglevel'):
                    env.append(('ROSCONSOLE_CONFIG_FILE', nm.settings().rosconsole_cfg_file(n.package)))
            for key, value in env:
                new_env[key] = value
            SupervisedPopen(shlex.split(utf8(' '.join(cmd_args))), cwd=cwd,
                            env=new_env, object_id="Run node", description="Run node "
                            "[%s]%s" % (utf8(n.package), utf8(n.type)))
            nm.filewatcher().add_binary(cmd_type, runcfg.node, runcfg.masteruri, runcfg.roslaunch_config.Filename)
        else:
            # 'print "RUN REMOTE", node, time.time()
            # start remote
            if runcfg.roslaunch_config.PackageName is None:
                raise StartException("Can't run remote without a valid package name!")
            # thus the prefix parameters while the transfer are not separated
            if prefix:
                prefix = ''.join(['"', prefix, '"'])
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn("env_loader in machine tag currently not supported")
                raise StartException("env_loader in machine tag currently not supported")
            if env:
                new_env = dict()
                try:
                    for (k, v) in env:
                        v_value, is_abs_path, found, package = cls._resolve_abs_paths(v, host, runcfg.user, runcfg.pw, runcfg.auto_pw_request)
                        new_env[k] = v_value
                        if is_abs_path:
                            abs_paths.append(('ENV', "%s=%s" % (k, v), "%s=%s" % (k, v_value)))
                            if not found and package:
                                not_found_packages.append(package)
                    env_command = "env " + ' '.join(["%s=\'%s\'" % (k, v) for (k, v) in new_env.items()])
                except nm.AuthenticationRequest as e:
                    raise nm.InteractionNeededError(e, cls.runNode, (runcfg,))

            startcmd = [env_command, nm.settings().start_remote_script,
                        '--package', utf8(n.package),
                        '--node_type', utf8(n.type),
                        '--node_name', utf8(runcfg.node),
                        '--node_respawn true' if n.respawn else '']
            if runcfg.masteruri is not None:
                startcmd.append('--masteruri')
                startcmd.append(runcfg.masteruri)
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]
            if runcfg.logging is not None:
                if not runcfg.logging.is_default('loglevel'):
                    startcmd.append('--loglevel')
                    startcmd.append(nm.settings().logging.loglevel)

            # rename the absolute paths in the args of the node
            node_args = []
            try:
                for a in n.args.split():
                    a_value, is_abs_path, found, package = cls._resolve_abs_paths(a, host, runcfg.user, runcfg.pw, runcfg.auto_pw_request)
                    node_args.append(a_value)
                    if is_abs_path:
                        abs_paths.append(('ARGS', a, a_value))
                        if not found and package:
                            not_found_packages.append(package)

                startcmd[len(startcmd):] = node_args
                startcmd[len(startcmd):] = args
                rospy.loginfo("Run remote on %s: %s", host, utf8(' '.join(startcmd)))
                # 'print "RUN CALL", node, time.time()
                _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, runcfg.user, runcfg.pw, runcfg.auto_pw_request, close_stdin=True)
                output = stdout.read()
                error = stderr.read()
                stdout.close()
                stderr.close()
                # 'print "RUN CALLOK", node, time.time()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(e, cls.runNode, (runcfg,))

            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", runcfg.node, error)
                    raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error])))
                if output:
                    rospy.loginfo("STDOUT while start '%s': %s", runcfg.node, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo("Absolute paths found while start:\n%s", utf8('\n'.join([''.join([p, '\n  OLD: ', ov, '\n  NEW: ', nv]) for p, ov, nv in abs_paths])))

            if len(not_found_packages) > 0:
                packages = '\n'.join(not_found_packages)
                raise StartException(utf8('\n'.join(['Some absolute paths are not renamed because following packages are not found on remote host:', packages])))