www.gusucode.com > robotsimulink 工具箱 matlab源码程序 > robotsimulink/robotslros/+robotics/+slros/+internal/+dlg/NetworkAddressSpecifier.m

    classdef NetworkAddressSpecifier < handle
    %This class is for internal use only. It may be removed in the future.
    
    %  NetworkAddressSpecifier opens a DDG dialog that lets the user inspect
    %  and modify the network addresses for ROS Master and Node Host that
    %  are used in Simulation. Once the user accepts the changes, the
    %  information is saved in MATLAB Preferences.
    % 
    %  Sample use:
    %   addr = robotics.slros.internal.dlg.NetworkAddressSpecifier;
    %   addr.openDialog
    
    %   Copyright 2014 The MathWorks, Inc.    
        
    properties(SetAccess=private)
        NetAddrStore
        Profile = robotics.slros.internal.sim.NetworkAddrProfile.empty
    end    
    
    methods
       
         function obj = NetworkAddressSpecifier
             obj.NetAddrStore = robotics.slros.internal.sim.NetworkAddrStore;             
             obj.Profile = obj.NetAddrStore.getProfile();
             
             if isempty(obj.Profile.MasterHost)
                 obj.Profile.MasterHost = obj.Profile.getDefaultMasterHost();
             end
             
             if isempty(obj.Profile.NodeHost)
                 obj.Profile.NodeHost = obj.Profile.getDefaultNodeHost();
             end
         end
         
         function dlg = openDialog(obj)
            dlg = DAStudio.Dialog(obj);
         end
        
        function dlgClose(obj, closeaction)
            % closeaction is
            %   'ok' if user clicked OK
            %   'cancel' if user clicked cancel or closed window
            try
                isAcceptedSelection = strcmpi(closeaction, 'ok');
                if isAcceptedSelection
                    obj.NetAddrStore.setProfile(obj.Profile);
                    obj.NetAddrStore.updateStore();
                end
            catch ME
                disp(ME.getReport);
                % Absorb all errors. If they are propagated back to
                % DDG, this causes MATLAB to crash, (Can't convert to
                % warnings are not as they are not displayed either).
            end                
        end
        
        
        function hostSelectionChanged(obj, dlg, tag, value)
            % value: 0 (Default), 1 (Custom)
            if strcmpi(tag, 'masterhost')
                obj.Profile.MasterUseDefault = (value == 0);
            else % strcmpi(tag, 'nodehost')
                obj.Profile.NodeUseDefault = (value == 0);
            end
            dlg.refresh;
        end
                   
        function hostNameChanged(obj, dlg, tag, value)
            if strcmpi(tag, 'masterHostName')   
                oldStr = obj.Profile.MasterHost;
            else % strcmpi(tag, 'nodeHostName')
                oldStr = obj.Profile.NodeHost;
            end

            newStr = obj.convertStrToHostName(value);
            if isempty(newStr)
                dlg.setWidgetValue(tag, oldStr);
                return;
            end
            
            if strcmpi(tag, 'masterHostName')   
                obj.Profile.MasterHost = newStr;
            else % strcmpi(tag, 'nodeHostName')
                obj.Profile.NodeHost = newStr;
            end
            
            dlg.setWidgetValue(tag, newStr);
        end

        function portChanged(obj, dlg, tag, value)             
             [num, numIsValid] = obj.convertStrToPortNum(value);
             if numIsValid                 
                 obj.Profile.MasterPort = num;
             end
             valueStr = sprintf('%d', obj.Profile.MasterPort);
             dlg.setWidgetValue(tag, valueStr);
        end
        
        function testMasterConnection(obj, dlg, tag) %#ok<INUSD>
            dlgTitle = message('robotics:robotslros:netaddrdlg:TestMasterDlgTitle').getString;            
            successImage = fullfile(matlabroot, 'toolbox', 'robotics', 'robotsimulink', 'robotslros', 'resources', 'success_32.png');
            errorImage = fullfile(matlabroot, 'toolbox', 'robotics', 'robotsimulink', 'robotslros', 'resources', 'error_32.png');
            
            dp = DAStudio.DialogProvider;
            dp.DialogImage = errorImage; % by default, show error icon
            
            waitingDlg = [];
            try
                % ROSMaster constructor can take a while since it attempts
                % to resolve hostname  (and throws error if it cannot). So,
                % put up the waiting dialog before invoking ROSMaster
                % Note -- MSGBOX ignores dp.DialogImage
                
                waitingDlg = dp.msgbox(...
                    message('robotics:robotslros:netaddrdlg:TestMasterChecking').getString, ...
                    dlgTitle, true);
                rosMaster = robotics.slros.internal.sim.ROSMaster(obj.Profile);                
                isReachable = rosMaster.isReachable();
                delete(waitingDlg);
                if isReachable
                    dp.DialogImage = successImage;
                    dp.errordlg(...
                        message('robotics:robotslros:netaddrdlg:TestMasterSuccess', ...
                        rosMaster.MasterURI).getString, ...
                        dlgTitle, true);
                else                    
                    dp.errordlg(...
                        message('robotics:robotslros:netaddrdlg:TestMasterFailure', ...
                        rosMaster.MasterURI).getString, ...
                        dlgTitle, true);                    
                end                
            catch ME
                if isa(waitingDlg, 'DAStudio.Dialog') && ishandle(waitingDlg)
                   delete(waitingDlg); 
                end
                if strcmpi(ME.identifier, 'robotics:ros:util:HostInvalid') || ...
                    strcmpi(ME.identifier, 'robotics:ros:util:InvalidRosMasterURIEnv') || ...
                    strcmpi(ME.identifier, 'robotics:ros:util:URIInvalid')
                    % Error thrown by ROSMaster constructor. It is messy to
                    % provide a customized message as we don't want to
                    % retrieve the ROS_MASTER_uri environment variable
                    % (adds unnecessary coupling). So, just display the
                    % message but suppress the stack.
                     dp.errordlg(ME.message, dlgTitle, true);
                else
                    dp.errordlg(ME.getReport('basic'), dlgTitle, true);
                end
            end
        end
        
        
        function dlgstruct = getDialogSchema(obj)             
            %% "ROS Master" section
            
            row=1;                        
            
            masterHostLabel.Name = message('robotics:robotslros:netaddrdlg:NetworkAddress').getString;
            masterHostLabel.Type  = 'text';
            masterHostLabel.Alignment  = 7;
            masterHostLabel.RowSpan = [row row];
            masterHostLabel.ColSpan = [1 1];
            masterHostLabel.Visible = true;
            
            masterHostSelection.Name = '';
            masterHostSelection.NameLocation = 6;
            masterHostSelection.Type  = 'combobox';
            masterHostSelection.Alignment = 0;
            masterHostSelection.RowSpan = [row row];
            masterHostSelection.ColSpan = [2 2];
            masterHostSelection.Entries = {
                message('robotics:robotslros:netaddrdlg:NetAddrDefault').getString
                message('robotics:robotslros:netaddrdlg:NetAddrCustom').getString
                };
            if obj.Profile.MasterUseDefault
                masterHostSelection.Value = 0;
            else
                masterHostSelection.Value = 1;
            end
            masterHostSelection.ObjectMethod = 'hostSelectionChanged'; % call method on UDD source object
            masterHostSelection.MethodArgs = {'%dialog', '%tag', '%value'}; % '%handle ' is implicit as first arg
            masterHostSelection.ArgDataTypes = {'handle', 'string', 'mxArray'};            
            masterHostSelection.Tag = 'masterhost';

            masterTestBtn.Name = message('robotics:robotslros:netaddrdlg:TestConnection').getString;
            masterTestBtn.Type = 'pushbutton';
            masterTestBtn.RowSpan = [row row];
            masterTestBtn.ColSpan = [3 3];            
            masterTestBtn.Alignment = 6; % top-left
            masterTestBtn.Tag = 'masterTestBtn';
            masterTestBtn.ObjectMethod = 'testMasterConnection'; % call method on UDD source object
            masterTestBtn.MethodArgs = {'%dialog', '%tag'}; % '%handle ' is implicit as first arg
            masterTestBtn.ArgDataTypes = {'handle', 'string'};
            
            row = row+1; 

            masterHostNameLabel.Name = message('robotics:robotslros:netaddrdlg:HostOrIPAddr').getString;
            masterHostNameLabel.Type  = 'text';
            masterHostNameLabel.Alignment  = 7;
            masterHostNameLabel.RowSpan = [row row];
            masterHostNameLabel.ColSpan = [1 1];
            masterHostNameLabel.Visible = ~obj.Profile.MasterUseDefault;
            
            masterHostName.Name = '';
            masterHostName.Type  = 'edit';
            masterHostName.Value = obj.Profile.MasterHost;
            masterHostName.RowSpan = [row row];
            masterHostName.ColSpan = [2 2];
            masterHostName.Alignment = 0; % top-left
            masterHostName.Tag = 'masterHostName';
            masterHostName.ObjectMethod = 'hostNameChanged'; % call method on UDD source object
            masterHostName.MethodArgs = {'%dialog', '%tag', '%value'}; % '%handle ' is implicit as first arg
            masterHostName.ArgDataTypes = {'handle', 'string', 'mxArray'};                        
            masterHostName.Visible = ~obj.Profile.MasterUseDefault;
            
            row = row+1;
            
            masterPortNumLabel.Name = message('robotics:robotslros:netaddrdlg:Port').getString;
            masterPortNumLabel.Type  = 'text';
            masterPortNumLabel.Alignment  = 7;
            masterPortNumLabel.RowSpan = [row row];
            masterPortNumLabel.ColSpan = [1 1];
            masterPortNumLabel.Visible = ~obj.Profile.MasterUseDefault;
            
            masterPortNum.Name = '';
            masterPortNum.Type = 'edit';
            masterPortNum.Value = sprintf('%d', obj.Profile.MasterPort);
            masterPortNum.RowSpan = [row row];
            masterPortNum.ColSpan = [2 2];
            masterPortNum.Alignment = 0; % top-left
            masterPortNum.Tag = 'masterPortNum';            
            masterPortNum.ObjectMethod = 'portChanged'; % call method on UDD source object
            masterPortNum.MethodArgs = {'%dialog', '%tag', '%value'}; % '%handle ' is implicit as first arg
            masterPortNum.ArgDataTypes = {'handle', 'string', 'mxArray'};              
            masterPortNum.Visible = ~obj.Profile.MasterUseDefault;                     

            row = row + 1;            
            
            masterDefaultHelp.Name = message('robotics:robotslros:netaddrdlg:MasterDefaultHelp').getString;            
            masterDefaultHelp.Type = 'text';
            masterDefaultHelp.Italic = 0;
            masterDefaultHelp.WordWrap = true;
            masterDefaultHelp.RowSpan = [row row]; 
            masterDefaultHelp.ColSpan = [1 3];
            masterDefaultHelp.Visible = obj.Profile.MasterUseDefault;               
                        
            row = row+1;             %#ok<NASGU>
            % container
            masterContainer.Type = 'group'; % can be 'panel', in which case, case use .Flat = true
            masterContainer.Name = message('robotics:robotslros:netaddrdlg:ROSMaster').getString;
            masterContainer.Flat = false;
            masterContainer.LayoutGrid = [4 3]; % [numrows numcolumns]
            masterContainer.ColStretch = [2 2 1];
            masterContainer.Items = {masterDefaultHelp, masterHostLabel, masterHostSelection, masterHostNameLabel,...
                masterHostName, masterPortNumLabel, masterPortNum, masterTestBtn};
            masterContainer.Visible = true;
            
            %% "Node Host" section
            
            row=1;
            nodeHelp.Name = message('robotics:robotslros:netaddrdlg:NodeHelp').getString;
            nodeHelp.Type = 'text';
            nodeHelp.Italic = 0;
            nodeHelp.WordWrap = true;
            nodeHelp.RowSpan = [row row]; 
            nodeHelp.ColSpan = [1 3];            

            row = row+1;                       

            nodeHostLabel.Name = message('robotics:robotslros:netaddrdlg:NetworkAddress').getString;
            nodeHostLabel.Type  = 'text';
            nodeHostLabel.Alignment  = 7;
            nodeHostLabel.RowSpan = [row row];
            nodeHostLabel.ColSpan = [1 1];
            nodeHostLabel.Visible = true;             
            
            nodeHostSelection.Name = '';
            nodeHostSelection.Type = 'combobox';
            nodeHostSelection.Alignment = 0;
            nodeHostSelection.RowSpan = [row row]; 
            nodeHostSelection.ColSpan = [2 2];
            nodeHostSelection.Entries = {
                message('robotics:robotslros:netaddrdlg:NetAddrDefault').getString
                message('robotics:robotslros:netaddrdlg:NetAddrCustom').getString
                };
            if obj.Profile.NodeUseDefault
                nodeHostSelection.Value = 0;
            else
                nodeHostSelection.Value = 1;
            end            
            nodeHostSelection.ObjectMethod = 'hostSelectionChanged'; % call method on UDD source object
            nodeHostSelection.MethodArgs = {'%dialog', '%tag', '%value'}; % '%handle ' is implicit as first arg
            nodeHostSelection.ArgDataTypes = {'handle', 'string', 'mxArray'};             
            nodeHostSelection.Tag = 'nodehost';

            row=row+1;
            
            nodeHostNameLabel.Name = message('robotics:robotslros:netaddrdlg:HostOrIPAddr').getString;
            nodeHostNameLabel.Type  = 'text';
            nodeHostNameLabel.Alignment  = 7;
            nodeHostNameLabel.RowSpan = [row row]; 
            nodeHostNameLabel.ColSpan = [1 1];
            nodeHostNameLabel.Visible = ~obj.Profile.NodeUseDefault;
            
            nodeHostName.Name = '';
            nodeHostName.Type  = 'edit';
            nodeHostName.Value = obj.Profile.NodeHost;
            nodeHostName.RowSpan = [row row]; 
            nodeHostName.ColSpan = [2 2];
            nodeHostName.Alignment = 0; % top-left
            nodeHostName.ObjectMethod = 'hostNameChanged'; % call method on UDD source object
            nodeHostName.MethodArgs = {'%dialog', '%tag', '%value'}; % '%handle ' is implicit as first arg
            nodeHostName.ArgDataTypes = {'handle', 'string', 'mxArray'};             
            nodeHostName.Tag = 'nodeHostName';
            nodeHostName.Visible = ~obj.Profile.NodeUseDefault;
            
            row = row+1;            
            
            nodeDefaultHelp.Name = message('robotics:robotslros:netaddrdlg:NodeDefaultHelp').getString;
            nodeDefaultHelp.Type = 'text';
            nodeDefaultHelp.Italic = 0;
            nodeDefaultHelp.WordWrap = true;
            nodeDefaultHelp.RowSpan = [row row]; 
            nodeDefaultHelp.ColSpan = [1 3];            
            nodeDefaultHelp.Visible = obj.Profile.NodeUseDefault;         
         
            % container
            nodeContainer.Type = 'group'; % can be 'panel', in which case, case use .Flat = true
            nodeContainer.Name =  message('robotics:robotslros:netaddrdlg:NodeHost').getString;
            nodeContainer.Flat = false;
            nodeContainer.LayoutGrid = [4 3]; % [numrows numcolumns]
            nodeContainer.ColStretch = [2 2 1];
            nodeContainer.Items = {nodeHelp, nodeHostLabel, nodeHostSelection, ...
                nodeHostNameLabel, nodeHostName, nodeDefaultHelp};
            nodeContainer.Visible = true;

            
            %% Main Dialog
            
            helptext.Name = message('robotics:robotslros:netaddrdlg:HelpText').getString;
            helptext.Type  = 'text';
            helptext.WordWrap = false;
            helptext.RowSpan = [1 1];
            helptext.ColSpan = [1 2];
            helptext.Tag = 'helptext';
            helptext.Visible = true;
            
            topLevelContainer.Type = 'group'; % can be 'panel', in which case, case use .Flat = true
            topLevelContainer.Name = '';
            topLevelContainer.Items = {helptext, masterContainer, nodeContainer};
            topLevelContainer.Visible = true;
            
            %% Main dialog struct
            
            dlgstruct.DialogTitle = message('robotics:robotslros:netaddrdlg:DialogTitle').getString;
            dlgstruct.HelpMethod = 'robotics.slros.internal.helpview';
            dlgstruct.HelpArgs =  {'rosConfigNetAddrDlg'}; % doc topic id
            dlgstruct.CloseMethod = 'dlgClose';            
            dlgstruct.CloseMethodArgs = {'%closeaction'};
            dlgstruct.CloseMethodArgsDT = {'string'};            
            
            % Make this dialog modal wrt to other DDG dialogs 
            % (doesn't block MATLAB command line)
            dlgstruct.Sticky = true; 
            
            % Buttons to show on dialog (these are options to pass to DDG,
            % not the final strings, so there is no need to use message
            % catalog)
            dlgstruct.StandaloneButtonSet =  ...
                {'Ok', 'Cancel', 'Help'}; % also available: 'Revert', 'Apply'            
            
            dlgstruct.Items = {topLevelContainer};
        end
    end
    
    %%
    methods(Static)
        function launch()
            % Convenience function for opening the dialog
            addr = robotics.slros.internal.dlg.NetworkAddressSpecifier;
            addr.openDialog();
        end
        
        function str = convertStrToHostName(str)
            % Attempt to enforce some basic hostname constraints
            str = regexprep(str, '[^0-9a-z-\.]', ''); % remove non alphanumeric chars
            str = regexprep(str, '\.+', '\.');  % remove sequences of periods
            str = regexprep(str, '(^\.|\.$)', ''); % remove prefixed & suffixed periods
        end
        
        function [num, isValid] = convertStrToPortNum(str)
            % str2double returns NaN if unable to convert
            num = str2double(str); 
            isValid = ~isnan(num);
            if isValid
                num = abs(fix(num));
                num = min(num, 65535);
                num = max(num, 1);
            end
        end
    end
    
end