def _process_listeners(self, name, exit_code):
        '''
          This is usually run as a post-executing function to the interaction and so will do the
          cleanup when the user's side of the interaction has terminated.

          Note that there are other means of stopping & cleanup for interactions:

          - via the remocon stop buttons (self.stop_interaction, self.stop_all_interactions)
          - via a rapp manager status callback when it is a pairing interaction

          There is some common code (namely del launched_interactions element, check pairing, publish remocon) so
          if changing that flow, be sure to check the code in self.stop_interaction()

          @param str name : name of the launched process stored in the interactions launch_list dict.
          @param int exit_code : could be utilised from roslaunched processes but not currently used.
        '''
        terminated = False
        for interaction in self.interactions_table.interactions:
            if self.launched_interactions.remove(interaction.hash, name):
                # toggle the pairing indicator if it was a pairing interaction
                if interaction.is_paired_type() and interaction.hash in self.active_paired_interaction_hashes:
                    self.active_paired_interaction_hashes = [interaction_hash for interaction_hash in self.active_paired_interaction_hashes if interaction_hash != interaction.hash]
                if not self.launched_interactions.get_launch_details(interaction.hash):
                    # inform the gui to update
                    self.signal_updated.emit()
                # update the rocon interactions handler
                self._publish_remocon_status()
                terminated = True
                break
        if not terminated:
            console.logwarn("A process listener detected a terminating interaction, but nothing to do.")
            console.logwarn("Probably mopped up by gui or independently terminating pairing requirement. [%s]" % name)
        else:
            console.logdebug("A process listener detected a terminating interaction & mopped up appropriately [%s]" % name)
 def start_interaction(self, interaction_hash):
     interaction = self.interactions_table.find(interaction_hash)
     if interaction is None:
         console.logerror("Couldn't find interaction with hash '%s'" % interaction_hash)
         return (False, "interaction key %s not found in interactions table" % interaction_hash)
     print("\nInteraction: %s" % interaction)
     console.logdebug("  - requesting permission to start interaction")
     response = self.service_proxies.request_interaction(remocon=self.name, hash=interaction_hash)
     if response.result == interaction_msgs.ErrorCodes.SUCCESS:
         console.logdebug("  - request granted")
         try:
             (app_executable, start_app_handler) = self._determine_interaction_type(interaction)
         except rocon_interactions.InvalidInteraction as e:
             return (False, ("invalid interaction specified [%s]" % str(e)))
         result = start_app_handler(interaction, app_executable)
         if result:
             if interaction.is_paired_type():
                 console.logdebug("  - setting an active pairing with %s" % interaction_hash)
                 self.active_paired_interaction_hashes.append(interaction_hash)
             self.signal_updated.emit()
             self._publish_remocon_status()
             return (result, "success")
         else:
             console.logerror("Result unknown")
             return (result, "unknown")
     else:
         console.logwarn("Request rejected [%s]" % response.message)
         return False, ("interaction request rejected [%s]" % response.message)
Exemple #3
0
    def __init__(self, context):
        self._context = context
        super(RqtRemocon, self).__init__(context)
        self.rocon_master_uri = None
        self.host_name = None

        ##############################
        # Environment Variables
        ##############################
        try:
            self.rocon_master_uri = os.environ["ROS_MASTER_URI"]
        except KeyError as unused_e:
            console.logerror("ROS_MASTER_URI not set, aborting")
            sys.exit(1)

        try:
            self.host_name = os.environ["ROS_HOSTNAME"]
        except KeyError as unused_e:
            console.logwarn("ROS_HOSTNAME not set, you may drop comms across a network connection.")
            self.host_name = 'localhost'

        ##############################
        # Launch User Interface
        ##############################

        self.setObjectName('Rqt Remocon')
        self.rqt_remocon = InteractionsChooserUI(self.rocon_master_uri, self.host_name, True)
        # self._rqt_remocon = InteractiveClientUI(None, "Rqt remocon", None, self.rocon_master_uri, self.host_name, True)
        context.add_widget(self.rqt_remocon.widget)
def load_rapp_specs_from_file(specification):
    '''
      Specification consists of resource which is file pointer. This function loads those files in memeory

      :param specification: Rapp Specification
      :type Specification: rocon_app_utilities.Rapp

      :returns Fully loaded rapp data dictionary
      :rtype: dict
    '''
    base_path = os.path.dirname(specification.filename)
    rapp_data = specification.raw_data

    data = {}
    data['name'] = specification.resource_name
    data['ancestor_name'] = specification.ancestor_name
    data['display_name']      = rapp_data.get('display', data['name'])
    data['description']       = rapp_data.get('description', '')
    data['compatibility']     = rapp_data['compatibility']
    data['launch']            = rapp_data['launch']
    data['launch_args']       = _get_standard_args(data['launch'])
    data['public_interface']  = rapp_data.get('public_interface', _default_public_interface())
    data['public_parameters'] = rapp_data.get('public_parameters', {})
    data['icon']              = rapp_data.get('icon', None)

    if 'pairing_clients' in rapp_data:
        console.logwarn('Rapp Indexer : [%s] includes "pairing_clients". It is deprecated attribute. Please drop it'%specification.resource_name)

    required_capabilities = 'required_capabilities'
    if required_capabilities in rapp_data:
        data[required_capabilities] = [c for c in rapp_data[required_capabilities]]

    return data
Exemple #5
0
    def _prepare_roslaunch_args(self, interaction_parameters):
        """
        Convert the interaction specified yaml string into roslaunch args
        to be passed to the roslaunchable. Note that we only use a constrained
        subset of yaml to be compatible with roslaunch args here.
        The root type has to be a dict and values themselves
        may not be dicts or lists.

        :param str interaction_parameters: parameters specified as a yaml string

        :returns: the parameters as roslaunch args key-value pairs
        :rtype: list of (name, value) pairs
        """
        args = []
        parameters = yaml.load(
            interaction_parameters
        )  # convert from yaml string into python dictionary
        if parameters is not None:
            if type(parameters) is types.DictType:
                for name, value in parameters.items():
                    if type(value) is types.DictType or type(
                            value) is types.ListType:
                        console.logwarn(
                            "Ignoring invalid parameter for roslaunch arg (simple key-value pairs only) [%s][%s]"
                            % (name, value))
                    else:
                        args.append((name, value))
            else:
                console.logwarn(
                    "Ignoring invalid parameters for roslaunch args (must be a simple key-value dict) [%s]"
                    % parameters)
        return args
Exemple #6
0
    def _process_listeners(self, name, exit_code):
        '''
          Callback function used to catch terminating applications and cleanup appropriately.

          @param name : name of the launched process stored in the interactions index.
          @type str

          @param exit_code : could be utilised from roslaunched processes but not currently used.
          @type int
        '''
        console.logdebug(
            "Interactive Client : process_listener detected terminating interaction [%s]"
            % name)
        for interaction in self._interactions_table.interactions:
            if name in interaction.launch_list:
                del interaction.launch_list[name]
                # toggle the pairing indicator if it was a pairing interaction
                if interaction.is_paired_type():
                    self.pairing = None
                if not interaction.launch_list:
                    # inform the gui to update
                    self._stop_interaction_postexec_fn()
                # update the rocon interactions handler
                self._publish_remocon_status()
            else:
                console.logwarn(
                    "Interactive Client : process_listener detected unknown terminating interaction [%s]"
                    % name)
Exemple #7
0
 def start_pairing(self, pairing):
     required_interaction = None
     if pairing.requires_interaction:
         required_interaction = self.interactions_table.find_by_name(
             pairing.requires_interaction)
         if required_interaction is None:
             response = interaction_srvs.StartPairingResponse()
             response.result = interaction_msgs.ErrorCodes.REQUIRED_INTERACTION_IS_NOT_AVAILABLE
             response.message = interaction_msgs.ErrorCodes.MSG_REQUIRED_INTERACTION_IS_NOT_AVAILABLE + " [{0}]".format(
                 pairing.requires_interaction)
             console.logwarn(
                 "%s [%s]" %
                 (response.message, pairing.requires_interaction))
             return response
     request = interaction_srvs.StartPairingRequest(pairing.name)
     response = self.service_proxies.start_pairing(request)
     if response.result == interaction_msgs.ErrorCodes.SUCCESS:
         if required_interaction is not None:
             (result, unused_message) = self.start_interaction(
                 required_interaction.hash)
             if not result:
                 self.stop_pairing(pairing)
                 response.result = interaction_msgs.ErrorCodes.REQUIRED_INTERACTION_FAILED
                 response.message = interaction_msgs.ErrorCodes.MSG_REQUIRED_INTERACTION_FAILED
     return response
Exemple #8
0
 def _stop_interaction(self):
     console.logdebug("Interactions Chooser : stopping interaction %s " % str(self.cur_selected_interaction.name))
     (result, message) = self.interactive_client.stop_interaction(self.cur_selected_interaction.hash)
     if result:
         if self.cur_selected_interaction.is_paired_type():
             self._refresh_interactions_list()  # make sure the highlight is disabled
         self._set_stop_interactions_button()
         #self.interactions_widget.stop_interactions_button.setDisabled(True)
     else:
         QMessageBox.warning(self, 'Stop Interaction Failed', "%s." % message.capitalize(), QMessageBox.Ok)
         console.logwarn("Interactions Chooser : stop interaction failed [%s]" % message)
Exemple #9
0
 def get_rocon_master_info(self):
     console.logdebug("RemoconInfo : retrieving rocon master information")
     time_out_cnt = 0
     while not rospy.is_shutdown():
         if len(self.rocon_master_info) != 0:
             break
         else:
             rospy.sleep(rospy.Duration(0.2))
         time_out_cnt += 1
         if time_out_cnt > 5:
             console.logwarn("RemoconInfo : timed out waiting for rocon master information")
             break
     return self.rocon_master_info
    def append(self, interaction):
        """
        Append an interaction to the table.

        :param :class:`.Interaction` interaction:
        """
        matches = [i for i in self.interactions if i.hash == interaction.hash]
        if not matches:
            self.interactions.append(interaction)
        else:
            console.logwarn(
                "Interactions Table : tried to append an already existing interaction [%s]"
                % interaction.hash)
Exemple #11
0
 def _set_stop_interactions_button(self):
     '''
       Disable or enable the stop button depending on whether the
       selected interaction has any currently launched processes,
     '''
     if not self.interactions:
         console.logwarn("No interactions")
         return
     if self.cur_selected_interaction.launch_list:
         console.logdebug("Interactions Chooser : enabling stop interactions button [%s]" % self.cur_selected_interaction.display_name)
         self.interactions_widget.stop_interactions_button.setEnabled(True)
     else:
         console.logdebug("Interactions Chooser : disabling stop interactions button [%s]" % self.cur_selected_interaction.display_name)
         self.interactions_widget.stop_interactions_button.setEnabled(False)
 def stop_interaction(self, interaction_hash):
     """
     This stops all launches for an interaction of a particular type.
     """
     interaction = self._interactions_table.find(interaction_hash)
     if interaction is None:
         error_message = "interaction key %s not found in interactions table" % interaction_hash
         console.logwarn(
             "Interactive Client : could not stop interactions of this kind [%s]"
             % error_message)
         return (False, "%s" % error_message)
     else:
         console.logdebug(
             "Interactive Client : stopping all '%s' interactions" %
             interaction.display_name)
     try:
         for launch_info in interaction.launch_list.values():
             if launch_info.running:
                 launch_info.shutdown()
                 console.loginfo(
                     "Interactive Client : interaction stopped [%s]" %
                     (launch_info.name))
                 del interaction.launch_list[launch_info.name]
             elif launch_info.process is None:
                 launch_info.running = False
                 console.loginfo(
                     "Interactive Client : no attached interaction process to stop [%s]"
                     % (launch_info.name))
                 del interaction.launch_list.launch_list[launch_info.name]
             else:
                 console.loginfo(
                     "Interactive Client : interaction is already stopped [%s]"
                     % (launch_info.name))
                 del interaction.launch_list.launch_list[launch_info.name]
     except Exception as e:
         console.logerror(
             "Interactive Client : error trying to stop an interaction [%s][%s]"
             % (type(e), str(e)))
         # this is bad...should not create bottomless exception buckets.
         return (False, "unknown failure - (%s)(%s)" % (type(e), str(e)))
     # console.logdebug("Interactive Client : interaction's updated launch list- %s" % str(interaction.launch_list))
     if interaction.is_paired_type():
         self.currently_pairing_interaction_hashes = [
             h for h in self.currently_pairing_interaction_hashes
             if h != interaction_hash
         ]
     self._publish_remocon_status()
     return (True, "success")
 def _start_command_line_interaction(self, interaction, command):
     '''
       Start a command line executable inside a shell window.
     '''
     console.logwarn("Starting command line executable [%s]" % interaction.command)
     cmd = command.split(' ')
     name = os.path.basename(cmd[0]).replace('.', '_')
     anonymous_name = name + "_" + uuid.uuid4().hex
     process_listener = functools.partial(self._process_listeners, anonymous_name, 1)
     console.logdebug("Command line executable: '%s'" % cmd)
     process = self.roslaunch_terminal.spawn_executable_window(interaction.name, cmd, postexec_fn=process_listener)
     self.launched_interactions.add(
         interaction.hash,
         anonymous_name,
         launch.LaunchInfo(anonymous_name, True, process)
     )
     return True
    def _process_listeners(self, name, exit_code):
        '''
          This is usually run as a post-executing function to the interaction and so will do the
          cleanup when the user's side of the interaction has terminated.

          Note that there are other means of stopping & cleanup for interactions:

          - via the remocon stop buttons (self.stop_interaction, self.stop_all_interactions)
          - via a rapp manager status callback when it is a pairing interaction

          There is some common code (namely del launch_list element, check pairing, publish remocon) so
          if changing that flow, be sure to check the code in self.stop_interaction()

          @param str name : name of the launched process stored in the interactions launch_list dict.
          @param int exit_code : could be utilised from roslaunched processes but not currently used.
        '''
        terminated = False
        for interaction in self._interactions_table.interactions:
            if name in interaction.launch_list:
                del interaction.launch_list[name]
                # toggle the pairing indicator if it was a pairing interaction
                if interaction.is_paired_type(
                ) and interaction.hash in self.currently_pairing_interaction_hashes:
                    self.currently_pairing_interaction_hashes = [
                        interaction_hash for interaction_hash in
                        self.currently_pairing_interaction_hashes
                        if interaction_hash != interaction.hash
                    ]
                if not interaction.launch_list:
                    # inform the gui to update
                    self._stop_interaction_postexec_fn()
                # update the rocon interactions handler
                self._publish_remocon_status()
                terminated = True
                break
        if not terminated:
            console.logwarn(
                "Interactive Client : detected a terminating interaction, but nothing to do [either mopped up via the gui or via rapp manager callback][%s]"
                % name)
        else:
            console.logdebug(
                "Interactive Client : detected terminating interaction and moppedddd up appropriately [%s]"
                % name)
Exemple #15
0
 def _start_global_executable_interaction(self, interaction, filename):
     console.logwarn(
         "Interactive Client : starting global executable [%s]" %
         interaction.name)
     name = os.path.basename(filename).replace('.', '_')
     anonymous_name = name + "_" + uuid.uuid4().hex
     process_listener = partial(self._process_listeners, anonymous_name, 1)
     cmd = [filename]
     remapping_args = []
     for remap in interaction.remappings:
         remapping_args.append(remap.remap_from + ":=" + remap.remap_to)
     cmd.extend(remapping_args)
     cmd.extend(
         self._prepare_command_line_parameters(interaction.parameters))
     console.logdebug("Interactive Client : global executable command %s" %
                      cmd)
     process = rocon_python_utils.system.Popen(cmd,
                                               postexec_fn=process_listener)
     interaction.launch_list[anonymous_name] = LaunchInfo(
         anonymous_name, True, process)
     return True
Exemple #16
0
    def _shutdown(self):
        if(self.is_connect != True):
            console.logwarn("RemoconInfo : tried to shutdown already disconnected remocon")
        else:
            console.logdebug("RemoconInfo : shutting down all apps")
            for app_hash in self.app_list.keys():
                self._stop_app(app_hash)

            self.app_list = {}
            self.is_connect = False

            rospy.signal_shutdown("shut down remocon_info")
            while not rospy.is_shutdown():
                rospy.rostime.wallsleep(0.1)

            self.is_connect = False
            self.info_sub.unregister()
            self.remocon_status_pub.unregister()

            self.info_sub = None
            self.remocon_status_pub = None
            console.logdebug("RemoconInfo : has shutdown.")
Exemple #17
0
 def _stop_interaction(self):
     """
     Stop running interactions when user hits `stop` or 'all stop interactions button` button.
     If no interactions is running, buttons are disabled.
     """
     console.logdebug("Interactions Chooser : stopping interaction %s " %
                      str(self.cur_selected_interaction.name))
     (result, message) = self.interactive_client_interface.stop_interaction(
         self.cur_selected_interaction.hash)
     if result:
         if self.cur_selected_interaction.is_paired_type():
             self.refresh_interactions_list(
             )  # make sure the highlight is disabled
         self._set_stop_interactions_button()
         # self.interactions_widget.stop_interactions_button.setDisabled(True)
     else:
         QMessageBox.warning(self.interactions_widget,
                             'Stop Interaction Failed',
                             "%s." % message.capitalize(), QMessageBox.Ok)
         console.logwarn(
             "Interactions Chooser : stop interaction failed [%s]" %
             message)
Exemple #18
0
def load_rapp_specs_from_file(specification):
    '''
      Specification consists of resource which is file pointer. This function loads those files in memeory

      :param specification: Rapp Specification
      :type Specification: rocon_app_utilities.Rapp

      :returns Fully loaded rapp data dictionary
      :rtype: dict
    '''
    base_path = os.path.dirname(specification.filename)
    rapp_data = specification.raw_data

    data = {}
    data['name'] = specification.resource_name
    data['ancestor_name'] = specification.ancestor_name
    data['display_name'] = rapp_data.get('display', data['name'])
    data['description'] = rapp_data.get('description', '')
    data['compatibility'] = rapp_data['compatibility']
    data['launch'] = rapp_data['launch']
    data['launch_args'] = _get_standard_args(data['launch'])
    data['public_interface'] = rapp_data.get('public_interface',
                                             _default_public_interface())
    data['public_parameters'] = rapp_data.get('public_parameters', {})
    data['icon'] = rapp_data.get('icon', None)

    if 'pairing_clients' in rapp_data:
        console.logwarn(
            'Rapp Indexer : [%s] includes "pairing_clients". It is deprecated attribute. Please drop it'
            % specification.resource_name)

    required_capabilities = 'required_capabilities'
    if required_capabilities in rapp_data:
        data[required_capabilities] = [
            c for c in rapp_data[required_capabilities]
        ]

    return data
Exemple #19
0
 def _start_interaction(self):
     """
     Start selected interactions when user hits start button and does doubleclicking interaction item.
     The interactions can be launched in duplicate.
     """
     console.logdebug("Interactions Chooser : starting interaction [%s]" %
                      str(self.cur_selected_interaction.name))
     (result,
      message) = self.interactive_client_interface.start_interaction(
          self.cur_selected_role, self.cur_selected_interaction.hash)
     if result:
         if self.cur_selected_interaction.is_paired_type():
             self.refresh_interactions_list(
             )  # make sure the highlight is working
         self.interactions_widget.stop_interactions_button.setDisabled(
             False)
     else:
         QMessageBox.warning(self.interactions_widget,
                             'Start Interaction Failed',
                             "%s." % message.capitalize(), QMessageBox.Ok)
         console.logwarn(
             "Interactions Chooser : start interaction failed [%s]" %
             message)
def check_if_executable_available(name):
    '''
      Ensure a particular executable is available on the system.

      Could use package names and python-apt here to find if the package is
      available, but more reliable and general - just check if program binary
      is available.

      Deprecated - aborts program execution with fatal error if not found.
    '''
    if which(name + 'z') is None:
        console.logwarn("Hub : " + name + " not found, either")
        console.logwarn("Hub :   1) it is there and you can't look up the admin PATH (ok - ignore this)")
        console.logwarn("Hub :   2) OR it is not installed - hint 'rosdep install rocon_hub'")