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

    classdef ParameterBase < ...
        matlab.System & ...
        matlab.system.mixin.internal.CustomIcon
    %This class is for internal use only. It may be removed in the future.
    
    %ParameterBase Base class for ROS parameter blocks
    
    %   Copyright 2015 The MathWorks, Inc.
        
    %#codegen
    %#ok<*EMCA>
    
    properties (Nontunable)       
        %ParameterName Name
        %   This system object will use ParameterName as specified in both
        %   simulation and code generation. In particular, it will not add a
        %   "/" in front of the name, as that forces the topic to be in the
        %   absolute namespace.        
        ParameterName = '/my_param'
        
        %ParameterSource Source
        %   By default, the user can choose a parameter name from the ROS
        %   network.
        ParameterSource = robotics.slros.internal.block.CommonMask.TopicSourceFromNetwork    

        %ParameterType Data type
        %   This is the data type of the Value output. Possible values are
        %   double, int32, uint8[] (string), and boolean. This data type is only valid in
        %   Simulink. For the corresponding MATLAB data type string, refer
        %   to the ParameterTypeML property.
        %   Default: 'double'
        ParameterType = 'double' 
    end
    
    % The following should ideally not show up in the MATLAB System block
    % dialog. However, setting them as 'Hidden' will prevent them from 
    % being accessible via set_param & get_param.
    % 
    %   ModelName is needed for managing the node instance
    %   BlockId is needed to generate a unique identifier in codegen
    properties (Nontunable)
        %ModelName - Name of Simulink model
        %   Used for managing the ROS node instance.
        ModelName = 'untitled'
        
        %BlockId - Simulink Block Identifier
        %   Used to generate unique identifier for the block during code
        %   generation. This should be obtained using Simulink.ID.getSID()
        %   on the library block (*not* the MATLAB system block). The
        %   SID has the format '<modelName>:<blocknum>'
        BlockId = 'param_'
        
        %StreamWSVar - Get and set parameters from variable in base workspace
        %   Used to redirect system objects to get and set parameters from a workspace
        %   variable instead of from ROS network (used for testing only).
        %   The workspace variable should be created like this:
        %
        %   workspaceVar = robotics.slros.internal.sim.ParameterListStream;
        %   workspaceVar.ParameterList = {paramValue1, paramValue2, paramValue3} );
        %   
        %   This capability of using workspace variables is only used in
        %   internal testing, and is not documented for Simulink users. 
        StreamWSVar = ''        
    end
        
    properties (Nontunable, Hidden)
        %ParameterTypeML - The ROS parameter type as MATLAB data type
        %   To avoid always converting back and forth between the two
        %   representations, I convert it once whenever the ParameterType
        %   is set.
        ParameterTypeML = 'double'    
    end  
    
    properties (Access = protected, Transient)
        %ROSMaster - Handle to an object that handles ROS master interaction
        %   It is initialized to indicate the class of the object.
        ROSMaster = robotics.slros.internal.sim.ROSMaster.empty 
        
        %ParameterStream - Handle to object that implements robotics.slros.internal.sim.ParameterStream
        %   This can be a sim.ParameterNetStream (for getting messages off
        %   the ROS network) or sim.ParameterListStream (for getting messages
        %   from an object in the base workspace; used in conjunction with
        %   StreamWsVar property)
        ParameterStream        
    end
    
    properties (Abstract, Access = protected)
        %MessageCatalogLibrary - The file for the block's message catalog library
        %   For example, this could be 'getparam' or 'setparam'
        MessageCatalogLibrary
        
        %StateHandler - Object handling the state of the parameter value 
        %   The derived classes will use a different object for handling
        %   scalar and array values.
        StateHandler
    end
    
    % These are the options for the dropdown lists
    % The properties are constant, hidden, and transient based on the
    % system object documentation
    properties (Constant, Hidden, Transient)
        %ParameterSourceSet - Dropdown choices for parameter source
        ParameterSourceSet = matlab.system.StringSet({...
            robotics.slros.internal.block.CommonMask.TopicSourceFromNetwork, ...
            robotics.slros.internal.block.CommonMask.TopicSourceSpecifyOwn});
        
        %ParameterTypeSet - Dropdown choices for parameter data type
        ParameterTypeSet = matlab.system.StringSet({'double', 'int32', 'boolean', ...
            robotics.slros.internal.sim.DataTypes.SimulinkStringType});
    end
    
    properties(Constant, Access = protected)
        %HeaderFile - Name of header file with declarations for variables and types
        %   It is referred to in code emitted by setupImpl and stepImpl.
        HeaderFile = robotics.slros.internal.cgen.Constants.InitCode.HeaderFile
    end    
    
    methods
        function set.ParameterName(obj, val)
            %set.ParameterName Set the parameter name
            %   The name is validated based on standard ROS naming rules
            %   and an error is thrown if the parameter name does not
            %   conform.
            
            validateattributes(val, {'char'}, {'nonempty'}, '', 'ParameterName');
            if coder.target('MATLAB')
                robotics.ros.internal.Namespace.canonicalizeName(val); % throws error
            end
            obj.ParameterName = val; 
        end
        
        function set.ParameterType(obj, val)
            %set.ParameterType Set the parameter type
            %   This is already a dropdown, so no separate data type
            %   validation is necessary.
            %   Convert the Simulink data type into the corresponding
            %   MATLAB data type.
            
            obj.ParameterTypeML = robotics.slros.internal.sim.DataTypes.simulinkToMatlab(val); %#ok<MCSUP>
            obj.ParameterType = val;
            
            % Set appropriate state handler for scalar and array parameters
            obj.initializeStateHandler;
        end
                
        function set.ModelName(obj, val)
            %set.ModelName Set model name property
            
            validateattributes(val, {'char'}, {'nonempty'}, '', 'ModelName');
            obj.ModelName = val;
        end
        
        function set.BlockId(obj, val)
            %set.BlockId Set block ID property
            
            validateattributes(val, {'char'}, {'nonempty'}, '', 'BlockId');
            obj.BlockId = val;
        end    
        
        function set.StreamWSVar(obj, val)
            %set.StreamWSVar Set parameter stream property
            
            validateattributes(val, {'char'}, {'nonempty'}, '', 'StreamWSVar');
            obj.StreamWSVar = val;
        end                    
    end
    
    methods (Access = protected)
        
        function out = constantSampleTimePropagationImpl(~)
            % Enable this system object to inherit constant ('inf') sample times
            out = 'Allow';
        end
        
        function initializeStateHandler(obj)
            %initializeStateHandler Set up the state handler
            
            % Make sure that StateHandler is initialized correctly
            isScalarType = robotics.slros.internal.sim.DataTypes.isSimulinkDataTypeScalar(obj.ParameterType);
            obj.setStateHandler(isScalarType);            
        end
        
        function setupImpl(obj)
            %setupImpl Model initialization call
            %   setupImpl is called when model is being initialized at the
            %   start of a simulation.
                        
            if coder.target('MATLAB')
                % Executing in MATLAB interpreted mode
                modelHasPriorState = robotics.slros.internal.sim.ModelStateManager.hasState(obj.ModelName);
                nodeRefCountIncremented = false;
                
                try %#ok<EMTC>
                    modelState = robotics.slros.internal.sim.ModelStateManager.getState(obj.ModelName, 'create');

                    % Initialize parameter stream (either from ROS network
                    % or from workspace variable)
                    obj.initializeParameterStream(modelState);
                    
                    modelState.incrNodeRefCount();
                    nodeRefCountIncremented = true; %#ok<NASGU>
                catch ME
                    if nodeRefCountIncremented
                        modelState.decrNodeRefCount(); %#ok<UNRCH>
                    end
                    if ~modelHasPriorState || ~modelState.nodeHasReferrers()
                        robotics.slros.internal.sim.ModelStateManager.clearState(obj.ModelName);
                    end
                    % RETHROW will generate a hard-to-read stack trace, so
                    % use THROW instead.
                    throw(ME);
                end
                
            elseif coder.target('RtwForRapid')
                % Rapid Accelerator. In this mode, coder.target('Rtw')
                % returns true as well, so it is important to check for
                % 'RtwForRapid' before checking for 'Rtw'
                msgId = ['robotics:robotslros:' obj.MessageCatalogLibrary ':RapidAccelNotSupported'];
                coder.internal.error(msgId);
                
            elseif  coder.target('Sfun')
                % 'Sfun'  - SimThruCodeGen target
                % Do nothing. MATLAB System block first does a pre-codegen
                % compile with 'Sfun' target, & then does the "proper"
                % codegen compile with Rtw or RtwForRapid, as appropriate.
                
            else
                % 'RtwForSim' - ModelReference SIM target
                % 'MEX', 'HDL', 'Custom' - Not applicable to MATLAB System block
                coder.internal.error('robotics:robotslros:sysobj:UnsupportedCodegenMode');
            end
        end        
        
        % We don't save SimState, since there is no way save & restore
        % the GetParameter object. However, saveObjectImpl and loadObjectImpl
        % are required since we have private properties.
        function s = saveObjectImpl(obj)
            % The errorIf() below will ensure that FastRestart cannot be used
            % in a model with ROS blocks
            coder.internal.error(['robotics:robotslros:' ...
                    obj.MessageCatalogLibrary ':SimStateNotSupported']);
            s = saveObjectImpl@matlab.System(obj);
        end
                
        function loadObjectImpl(obj,s,wasLocked)            
            loadObjectImpl@matlab.System(obj,s,wasLocked);
        end   
        
        %%
        function releaseImpl(obj)
            if coder.target('MATLAB')
                st = robotics.slros.internal.sim.ModelStateManager.getState(obj.ModelName);
                st.decrNodeRefCount();
                
                if  ~st.nodeHasReferrers()
                    robotics.slros.internal.sim.ModelStateManager.clearState(obj.ModelName);
                end
            else % coder.target('Rtw')
                % Nothing to do. The system object will never be released
                % in the generated node.
            end
        end       
        
        function initializeParameterStream(obj, modelState)
            %initializeParameterStream Initialize the ParameterStream property
            %   The stream is either connected to the ROS network or
            %   connected to a workspace variable.
            
            if ~isempty(obj.StreamWSVar)
                % Use a variable in MATLAB Workspace as source of messages.
                obj.ParameterStream = evalin('base', obj.StreamWSVar);
                validateattributes(obj.ParameterStream, {'robotics.slros.internal.sim.ParameterListStream'}, {'scalar'}, ...
                    'setup', 'ParameterStream');
            else
                % Use ROS network as a source of parameters.
                if isempty(modelState.ROSNode) || ~isvalid(modelState.ROSNode)
                    obj.ROSMaster = robotics.slros.internal.sim.ROSMaster();
                    %  verifyReachable() errors if ROS master is unreachable
                    obj.ROSMaster.verifyReachable();
                    % createNode() errors if unable to create node
                    % (e.g., if node with same name already exists)
                    uniqueName = obj.ROSMaster.makeUniqueName(obj.ModelName);
                    modelState.ROSNode = obj.ROSMaster.createNode(uniqueName);
                end
                
                % Initialize the MATLAB ROS parameter stream
                obj.ParameterStream = robotics.slros.internal.sim.ParameterNetStream(...
                    obj.ParameterName, modelState.ROSNode);
            end
        end
    end
    
    methods(Static, Access = protected)        
        function simMode = getSimulateUsingImpl
            %getSimulateUsingImpl Restrict simulation mode to interpreted execution
            simMode = 'Interpreted execution';
        end
        
        function flag = showSimulateUsingImpl
            %showSimulateUsingImpl Do now show simulation execution mode dropdown in block mask
            flag = false;
        end
    end
    
    %% Methods that need to be implemented by derived classes
    methods (Abstract, Access = protected)
        setStateHandler(obj, isScalar)
        %setStateHandler Set the correct state handler object (for scalar or array parameter)
    end
end