Main Content

Using Mapping Modes with Custom-Mapped External Inputs

This example shows how to implement a custom mapping algorithm similar to a Simulink® mapping mode. It uses the getSlRootInportMap and getRootInportMap functions to implement the custom mapping.

Before running this example, make sure that you are familiar with the getRootInportMap command and the Root Inport Mapper Tool. For more information, see Map Root Inport Signal Data.

Workflow

This example shows how you can use a built-in Simulink mapping mode to perform as many mappings as possible. It then flags the root inports that were not able to be assigned a signal. The algorithm then overrides the flagged mappings with custom mappings to map the remaining signals. To implement such a solution, create a custom mapping function using the getSlRootInportMap.

This example uses a list of inputs with two kinds of signals:

  • Signals that can be mapped using the Simulink block name mapping mode.

  • Signals that cannot be mapped using the Simulink block name mapping mode. You must map these signals with a custom mapping mode.

Assume the following scenario:

  • You want to use a group of signals as inputs to your Simulink model.

  • The signals are named such that the variable names match the block name of the root-level inport.

  • Each signal that uses this naming convention is within tolerance.

  • Each signal that has the 'x' character appended to its name is considered outside tolerance.

This example uses a mapping mode similar to the Simulink block name mapping method.

The root-level inport block names are:

  • Throttle

  • Brake

The signal variable names are:

  • Throttlex

  • Brake

To map inputs to root-level inport blocks in this scenario, you need a custom mapping function for the Root Inport Mapper tool. This example uses the AlmostBlockName custom mapping function.

For this example, you will use the slexAutotransRootInportsExample model to validate your custom mapping function.

Declare the Custom Mapping Function

Declare the function name, inputs, and outputs. To do this, copy and paste the following code snippet into a MATLAB® file and save the file as AlmostBlockName.m.

function inputMap = AlmostBlockName( modelName, signalNames, signals )

Get the Simulink BlockName Mapping

Next, map all the signals. To do this, first map all the signals within tolerance using the Simulink block name mapping mode, then map the signals outside tolerance.

To map signals within tolerance to a model using one of the Simulink mapping modes, use the function getSlRootInportMap. This function returns the inputMap and a vector of logical values. Each logical value indicates a successful or unsuccessful mapping of inputMap to a signal. To map by block name, insert the following lines of code just after the function declaration.

inputMap = getRootInportMap('empty');
if ~bdIsLoaded(modelName)
   load_system(modelName);
end
[inputMap, hasASignal] = getSlRootInportMap('Model', modelName, ...
        'MappingMode','BlockName',...
        'signalName',signalNames, 'signalValue', signals);

Find the Missing Input Signals

In the previous step, you created a mapping using a block name mapping mode. You must now account for an empty inputMap and for inputMap(s) that were not associated with a signal within tolerance. The function getSlRootInportMap has flagged these signals with the output variable hasASignal. To do this:

  1. Check the inputMap variable.

  2. If the inputMap variable is not empty, determine which elements of the inputMap vector were not assigned a signal. To do this, use the logical ~ on the hasASignal vector as shown below. The emptyIndex vector now contains a logical vector where true means the inputMap does not have a signal mapped to it.

  3. Copy and paste the following code snippet under the call to the getSlRootInportMap and before the end to the if bdIsLoaded(modelName).

if ~isempty(inputMap)
    emptyIndex = ~hasASignal;
end

The code snippet performs steps one and two for you.

Complete the Mapping

In the previous step, you created a logical vector emptyIndex to see if any of the inputMap objects were not associated to a signal. If all the elements of the emptyIndex vector are false, you have a complete mapping and the code added in this section will not be executed.

If the emptyIndex vector contains at least one value that is true, you have inputMap objects that are not associated to a signal. Manually assign the variable signal(s) to that inputMap. Then, override the inputMap with the signal name that matches the expected signal name:

  1. In the emptyIndex vector, find all the items that are true. These items point to the inputMap(s) that still need to be associated with a signal.

  2. For each inputMap, use the 'BlockName' property to get the name of the inport block that the inputMap is assigned to.

  3. Append an 'x' to the block name to get the name of the signal to be assigned to the inputMap.

  4. Compare the result to each item in the signalNames variable cell array.

  5. If a match is found, override the inputMap with the signal name that matches the expected signal name. To override the inputMap object, use the getRootInportMap function with the 'InputMap' and the 'SignalName' properties.

if isa( signals{1}, 'Simulink.SimulationData.Dataset')
    signalNames = signals{1}.getElementNames';
end
idxEmpty = find(emptyIndex==true);
for kEmpty =1:length(idxEmpty)
    idxOfEmpty = idxEmpty(kEmpty);
    destBlockName = get(inputMap(idxOfEmpty),'BlockName');
    outSideToleranceSig = [destBlockName 'x'];
    isAMatch = strcmp(signalNames, outSideToleranceSig);
    if any(isAMatch)
        inputMap(idxOfEmpty) = getRootInportMap('InputMap', ...
            inputMap(idxOfEmpty),'SignalName',outSideToleranceSig);
    end
end

The Custom Map File

When you are done, the file AlmostBlockName.m should resemble the following code.

function inputMap = AlmostBlockName(modelName, signalNames, signals)
inputMap = getRootInportMap('empty');
if bdIsLoaded(modelName)
     [inputMap, hasASignal] = getSlRootInportMap('Model', modelName, ...
     'MappingMode','BlockName',...
     'signalName',signalNames, 'signalValue', signals);
     if ~isempty(inputMap)
        emptyIndex = ~hasASignal;
        idxEmpty = find(emptyIndex==1);
        if isa( signals{1}, 'Simulink.SimulationData.Dataset')
             signalNames = signals{1}.getElementNames';
        end
        for kEmpty =1:length(idxEmpty)
            idxOfEmpty = idxEmpty(kEmpty);
            destBlockName = get(inputMap(idxOfEmpty),'BlockName');
            nonNominalSig = [destBlockName 'x'];
            isAMatch = strcmp(signalNames, nonNominalSig);
            if any(isAMatch)
                inputMap(idxOfEmpty) = getRootInportMap('InputMap', ...
                    inputMap(idxOfEmpty),'SignalName',nonNominalSig);
            end
        end
     end
end

Validate the Custom Mapping

To validate your custom mapping:

  1. Save the AlmostBlockName function in a file on the MATLAB path.

  2. To see the results of your mapping function, copy and paste the following code snippet to the MATLAB Command Window.

modelName  = 'slexAutotransRootInportsExample';
Throttlex  = timeseries(zeros(10,1));
Brake      = timeseries(ones(10,1));
signalNames= {'Throttlex' ,'Brake'};
signals    = { Throttlex  , Brake };
open_system(modelName);
inputMap   = AlmostBlockName(modelName, signalNames, signals);
inputStr   = getInputString(inputMap,'base');
close_system(modelName);

After running the code snippet, the variable inputStr contains the string 'Throttlex,Brake'.

If your signals are in a Simulink.SimulationData.Dataset, to see the results of your mapping function, use the following code snippet at the MATLAB Command Window.

modelName  = 'slexAutotransRootInportsExample';
Throttlex  = timeseries(zeros(10,1));
Brake      = timeseries(ones(10,1));
ds         = Simulink.SimulationData.Dataset;
ds         = ds.addElement( Throttlex, 'Throttlex' );
ds         = ds.addElement( Brake, 'Brake' );
signalNames= {'ds'};
signals    = { ds };
open_system(modelName);
inputMap   = AlmostBlockName(modelName, signalNames, signals);
inputStr   = getInputString(inputMap,'base');
close_system(modelName);

After running the code snippet for signals in a Simulink.SimulationData.Dataset, the variable inputStr contains the string 'ds.getElement('Throttlex'),ds.getElement('Brake')'.

See Also

|

Related Examples

More About