Использование режимов отображения с пользовательскими внешними входами

Этот пример показывает, как реализовать пользовательский алгоритм отображения, подобный режиму отображения Simulink. Он использует getSlRootInportMap и getRootInportMap функций для реализации пользовательского отображения.

Этот пример принимает, что вы знакомы с getRootInportMap команда и пользовательская возможность отображения Root Inport Mapper Tool. Если вы не знакомы с этими концепциями, см. Map Root Inport Signal Data.

Рабочий процесс

В этом примере показано, как можно использовать встроенный режим отображения Simulink для выполнения как можно большего количества отображений. Затем он помечает корневые входные порты, которым не удалось назначить сигнал. Затем алгоритм переопределяет отмеченные преобразования пользовательскими отображениями, чтобы сопоставить оставшиеся сигналы. Чтобы реализовать такое решение, создайте пользовательскую функцию отображения с помощью getSlRootInportMap.

Этот пример использует список входов с двумя видами сигналов:

  • Сигналы, которые могут быть отображены с помощью режима отображения имени блока Simulink.

  • Сигналы, которые не могут быть сопоставлены с использованием режима отображения имен блоков Simulink. Вы должны сопоставить эти сигналы с пользовательским режимом отображения.

Примите следующий сценарий:

  • Вы хотите использовать группу сигналов в качестве входов для вашей модели Simulink.

  • Сигналы названы так, что имена переменных совпадают с именем блока входного порта корневого уровня.

  • Каждый сигнал, который использует это соглашение об именовании, находится в пределах допуска.

  • Каждый сигнал, который имеет символ 'x', добавленный к его имени, рассматривается как внешний допуск.

Этот пример использует режим отображения, подобный методу сопоставления имен блоков Simulink.

Имена блоков входных портов корневого уровня:

  • Дроссель

  • Тормоз

Имена переменных сигнала:

  • Throttlex

  • Тормоз

Чтобы сопоставить входы блокам входных портов корневого уровня в этом сценарии, вам нужна пользовательская функция отображения для инструмента Root Inport Mapper. Этот пример использует пользовательскую функцию сопоставления LatelyBlockName.

В данном примере вы будете использовать slexAutotransRootInportsExample модель, чтобы подтвердить свою пользовательскую функцию отображению.

Объявление пользовательской функции отображения

Объявите имя функции, входы и выходы. Для этого скопируйте и вставьте следующий фрагмент кода в файл MATLAB и сохраните файл как LatelyBlockName.m.

function inputMap = AlmostBlockName( modelName, signalNames, signals )

Получите отображение Simulink BlockName

Затем сопоставьте все сигналы. Для этого сначала сопоставьте все сигналы в пределах допуска с помощью режима отображения имени блока Simulink, затем сопоставьте сигналы вне допуска.

Чтобы сопоставить сигналы в пределах допуска с моделью с помощью одного из режимов отображения Simulink, используйте функцию getSlRootInportMap. Эта функция возвращает inputMap и вектор логических значений. Каждое логическое значение указывает на успешное или неудачное отображение inputMap к сигналу. Чтобы сопоставить по имени блока, вставьте следующие строки кода сразу после объявления функции.

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

Найдите отсутствующие входные сигналы

На предыдущем шаге вы создали отображение с использованием режима отображения имен блоков. Теперь необходимо указать пустую inputMap и для inputMap(s) которые не были связаны с сигналом в пределах допуска. Функция getSlRootInportMap пометил эти сигналы переменного выхода hasASignal. Для этого:

  1. Проверьте inputMap переменная.

  2. Если на inputMap переменная не пуста, определите, какие элементы inputMap вектору не был назначен сигнал. Для этого используйте логическую ~ на hasASignal вектор, как показано ниже. The emptyIndex теперь вектор содержит логический вектор, где true означает inputMap не имеет сигнала, сопоставленного с ним.

  3. Скопируйте и вставьте следующий фрагмент кода под вызовом в getSlRootInportMap и перед концом на bdIsLoaded(modelName) if.

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

Фрагмент кода выполняет шаги один и два для вас.

Завершите отображение

На предыдущем шаге вы создали логический вектор emptyIndex чтобы увидеть, не были ли какие-либо объекты inputMap связаны с сигналом. Если все элементы вектора emptyIndex имеют значение false, у вас есть полное отображение, и код, добавленный в этот раздел, не будет выполнен.

Если на emptyIndex вектор содержит по крайней мере одно значение, которое true, вы имеете inputMap объекты, которые не связаны с сигналом. Вручную присвойте сигнал (ы) переменной этому inputMap. Затем переопределите inputMap с именем сигнала, которое совпадает с именем ожидаемого сигнала:

  1. В векторе emptyIndex найдите все элементы, которые являются true. Эти элементы указывают на inputMap(s) который все еще должен быть связан с сигналом.

  2. Для каждого inputMap, используйте свойство 'BlockName', чтобы получить имя входного блока, который inputMap назначается.

  3. Добавьте 'x' к наименованию блока, чтобы получить имя сигнала, который будет назначен inputMap.

  4. Сравните результат с каждым элементом массива ячеек переменной signalNames.

  5. Если совпадение найдено, переопределите inputMap с именем сигнала, которое совпадает с именем ожидаемого сигнала. Чтобы переопределить inputMap объект, используйте функцию getRootInportMap со свойствами 'InputMap' и 'SignalName'.

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

Пользовательский файл карты

Когда вы сделаны, файл LatelyBlockName.m должен напоминать следующий код.

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

Проверьте пользовательское отображение

Чтобы проверить пользовательское отображение:

  1. Сохраните функцию LatelyBlockName в файле на пути MATLAB.

  2. Чтобы увидеть результаты функции отображения, скопируйте и вставьте следующий фрагмент кода в Командное окно MATLAB.

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);

После выполнения фрагмента кода переменная inputStr содержит строку 'Throttlex, Brake'.

Если ваши сигналы находятся в Simulink .SimulationData. Набор данных, чтобы увидеть результаты вашей функции отображения, используйте следующий фрагмент кода в Командном окне MATLAB.

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);

После выполнения фрагмента кода для сигналов в Simulink .SimulationData. Набор данных, переменная inputStr содержит строку 'ds.getElement (' Throttlex '), ds.getElement (' Brake ')'.