Пример по верификации командной строки

Этот пример создает три теста для ограничителя регулируемой процентной ставки и анализирует получившееся покрытие модели с помощью API командной строки Инструмента model coverage.

Модель Simulink® для ограничителя регулируемой процентной ставки

Ограничитель Регулируемой процентной ставки подсистемы Simulink® является ограничителем уровня в модели 'slvnvdemo_ratelim_harness'. Это использует три блока switch, чтобы управлять, когда выход должен быть ограничен и тип предела, чтобы применяться.

Входные параметры производятся с Из блоков Рабочей области 'усиление', 'возрастающий предел', и 'падающий предел', которые генерируют кусочные линейные сигналы. Значения входных параметров заданы с шестью переменными, заданными в рабочей области MATLAB®: t_gain, u_gain, t_pos, u_pos, t_neg, и u_neg.

open_system('slvnvdemo_ratelim_harness');
open_system('slvnvdemo_ratelim_harness/Adjustable Rate Limiter');

Создание первого теста

Первый тест проверяет, что выход совпадает с входом, когда входные значения не изменяются быстро. Это использует синусоиду в качестве времени, варьируясь сигнал и константы для повышения и падения пределов.

t_gain = (0:0.02:2.0)';
u_gain = sin(2*pi*t_gain);

Вычислите минимальное и максимальное изменение входа варьирования времени с помощью функции diff MATLAB.

max_change = max(diff(u_gain))
min_change = min(diff(u_gain))
max_change =

    0.1253


min_change =

   -0.1253

Поскольку изменения сигнала очень меньше 1 и намного больше, чем-1, установите ограничения скорости для 1 и-1. Переменные все хранятся в файле MAT 'within_lim.mat', который загружается перед симуляцией.

t_pos = [0;2];
u_pos = [1;1];
t_neg = [0;2];
u_neg = [-1;-1];

save('within_lim.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

Дополнительные тесты

Второй тест дополняет первый случай возрастающим усилением, которое превышает ограничение скорости. После секунды это увеличивает ограничение скорости так, чтобы изменения усиления были ниже того предела.

t_gain = [0;2];
u_gain = [0;4];
t_pos = [0;1;1;2];
u_pos = [1;1;5;5]*0.02;
t_neg = [0;2];
u_neg = [0;0];

save('rising_gain.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

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

t_gain = [0;2];
u_gain = [-0.02;-4.02];
t_pos = [0;2];
u_pos = [0;0];
t_neg = [0;1;1;2];
u_neg = [-1;-1;-5;-5]*0.02;

save('falling_gain.mat','t_gain','u_gain','t_pos','u_pos','t_neg','u_neg');

Определение тестов покрытия

Тесты организованы и выполнили использование cvtest и cvsim команды. Эти команды заменяют sim команда, которая обычно используется, чтобы программно выполнить симуляции Simulink.

cvtest команда используется, чтобы указать информацию о тестовой симуляции. Требуются следующие три аргумента:

  • полный путь к корневой подсистеме инструментирования (или только имя модели, чтобы оснастить целую модель)

  • строка метки используется в создании отчетов

  • команда настройки, которая оценена в базовом рабочем пространстве только до запуска симуляции.

testObj1 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Gain within slew limits', ...
                  'load(''within_lim.mat'');')
 testObj1 = ... cvtest
                  id: 745 (READ ONLY)
            modelcov: 735 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Gain within slew limits
            setupCmd: load('within_lim.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

Другие тестовые объекты так же подготовлены:

testObj2 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Rising gain that temporarily exceeds slew limit', ...
                  'load(''rising_gain.mat'');')

testObj3 = cvtest('slvnvdemo_ratelim_harness/Adjustable Rate Limiter', ...
                  'Falling gain that temporarily exceeds slew limit', ...
                  'load(''falling_gain.mat'');')
 testObj2 = ... cvtest
                  id: 747 (READ ONLY)
            modelcov: 735 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Rising gain that temporarily exceeds slew limit
            setupCmd: load('rising_gain.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

 testObj3 = ... cvtest
                  id: 749 (READ ONLY)
            modelcov: 735 (READ ONLY)
            rootPath: Adjustable Rate Limiter
               label: Falling gain that temporarily exceeds slew limit
            setupCmd: load('falling_gain.mat');
            settings: [1x1 struct]
    modelRefSettings: [1x1 struct]
         emlSettings: [1x1 struct]
        sfcnSettings: [1x1 struct]
             options: [1x1 struct]
              filter: 

Выполнение тестов покрытия

Выполните тестовый объект покрытия для первого теста с помощью cvsim команда. Это заставляет модель начинать симуляцию.

cvsim синтаксис команд похож на это для встроенной sim команды, за исключением того, что первый вход и первые выходные аргументы являются cvtest и объектами cvdata, соответственно. Результаты симуляции получены с помощью нескольких возвращаемых значений.

[dataObj1,T,X,Y] = cvsim(testObj1,[0 2]);
dataObj1
dataObj1 = ... cvdata
                 id: 751
               type: TEST_DATA
               test: cvtest object
             rootID: 753
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 29-Jan-2020 15:11:08
           stopTime: 29-Jan-2020 15:11:08
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

Проверьте первый тест путем проверки, что выход совпадает с входом.

subplot(211),plot(T,Y(:,1),T,Y(:,4)),xlabel('Time (sec)'),ylabel('Value'),
title('Gain input and output');
subplot(212),plot(T,Y(:,1)-Y(:,4)),xlabel('Time (sec)'),ylabel('Difference'),
title('Difference between the gain input and output');

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

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

[dataObj2,T,X,Y] = cvsim(testObj2,[0 2]);
dataObj2

subplot(211),plot(T,Y(:,1),T,Y(:,4)),xlabel('Time (sec)'),ylabel('Value'),
title('Gain input and output');
subplot(212),plot(T,Y(:,1)-Y(:,4)),xlabel('Time (sec)'),ylabel('Difference'),
title('Difference between the gain input and output');
dataObj2 = ... cvdata
                 id: 874
               type: TEST_DATA
               test: cvtest object
             rootID: 753
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 29-Jan-2020 15:11:10
           stopTime: 29-Jan-2020 15:11:10
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

Выполните и постройте результаты для третьего теста.

[dataObj3,T,X,Y] = cvsim(testObj3,[0 2]);
dataObj3

subplot(211), plot(T,Y(:,1),T,Y(:,4)), xlabel('Time (sec)'), ylabel('Value'),
title('Gain input and output');
subplot(212), plot(T,Y(:,1)-Y(:,4)), xlabel('Time (sec)'), ylabel('Difference'),
title('Difference between the gain input and output');
dataObj3 = ... cvdata
                 id: 980
               type: TEST_DATA
               test: cvtest object
             rootID: 753
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 29-Jan-2020 15:11:11
           stopTime: 29-Jan-2020 15:11:11
  intervalStartTime: 0
   intervalStopTime: 0
simulationStartTime: 0
 simulationStopTime: 2
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

Генерация отчета покрытия

При предположении, что все тесты передали, представьте объединенный отчет от всех тестов, чтобы проверить достижение 100%-го покрытия. Проценты покрытия для каждого теста отображены под направляющейся "Иерархией модели". Несмотря на то, что ни один из тестов индивидуально не достиг 100%-го покрытия в агрегате, они достигают полного обзора.

cvhtml('combined_ratelim',dataObj1,dataObj2,dataObj3);

Сохранение данных о покрытии

Используйте cvsave команда, чтобы сохранить настройку теста и результаты покрытия в текстовом файле "ratelim_testdata.cvt" для более позднего анализа.

cvsave('ratelim_testdata','slvnvdemo_ratelim_harness');

Закройте модель и выйдите из среды покрытия

close_system('slvnvdemo_ratelim_harness',0);
clear dataObj*
clear testObj*

Загрузка данных о покрытии

Используйте cvload команда, чтобы восстановить сохраненные тесты покрытия из файла "ratelim_testdata.cvt" после открытия модели. Данные и тесты получены в массиве ячеек.

open_system('slvnvdemo_ratelim_harness');
[SavedTests,SavedData] = cvload('ratelim_testdata')
SavedTests =

  1x3 cell array

    {1x1 cvtest}    {1x1 cvtest}    {1x1 cvtest}


SavedData =

  1x3 cell array

    {1x1 cvdata}    {1x1 cvdata}    {1x1 cvdata}

Управление объектами данных покрытия

Используйте перегруженные операторы, +, - и *, чтобы управлять объектами cvdata. Оператор * используется, чтобы найти пересечение двух объектов данных покрытия, которое приводит к другому объекту cvdata. Например, следующая команда производит отчет HTML общего покрытия от всех трех тестов.

common = SavedData{1} * SavedData{2} * SavedData{3}
cvhtml('intersection',common)
common = ... cvdata
                 id: 0
               type: DERIVED_DATA
               test: []
             rootID: 1089
           checksum: [1x1 struct]
          modelinfo: [1x1 struct]
          startTime: 29-Jan-2020 15:11:08
           stopTime: 29-Jan-2020 15:11:11
  intervalStartTime: 0
   intervalStopTime: 0
            metrics: [1x1 struct]
             filter: 
            simMode: Normal

Извлечение информации от объектов данных покрытия

decisioninfo команда получает информацию о покрытии из блока path или указателя блока. Выход является вектором с достигнутыми и общими результатами для одного объекта модели.

cov = decisioninfo(SavedData{1} + SavedData{2} + SavedData{3}, ...
                   'slvnvdemo_ratelim_harness/Adjustable Rate Limiter')
cov =

     6     6

Используйте эту полученную информацию о покрытии, чтобы получить доступ к ее покрытию процента можно следующим образом:

percentCov = 100 * (cov(1)/cov(2))
percentCov =

   100

Когда два выходных аргумента используются, decisioninfo команда возвращает структуру, которая получает решения и результаты в объекте Stateflow® или блоке Simulink.

[blockCov,desc] = decisioninfo(common, ...
         'slvnvdemo_ratelim_harness/Adjustable Rate Limiter/Delta sign')
descDecision = desc.decision
outcome1 = desc.decision.outcome(1)
outcome2 = desc.decision.outcome(2)
blockCov =

     0     2


desc = 

  struct with fields:

           isFiltered: 0
    justifiedCoverage: 0
          isJustified: 0
      filterRationale: ''
             decision: [1x1 struct]


descDecision = 

  struct with fields:

               text: 'Switch trigger'
    filterRationale: ''
         isFiltered: 0
        isJustified: 0
            outcome: [1x2 struct]


outcome1 = 

  struct with fields:

               text: 'false (out = in3)'
     executionCount: 0
         executedIn: []
         isFiltered: 0
        isJustified: 0
    filterRationale: ''


outcome2 = 

  struct with fields:

               text: 'true (out = in1)'
     executionCount: 0
         executedIn: []
         isFiltered: 0
        isJustified: 0
    filterRationale: ''

Для просмотра документации необходимо авторизоваться на сайте