Этот пример создает три теста для ограничителя регулируемой процентной ставки и анализирует получившееся покрытие модели с помощью API командной строки Инструмента model coverage.
Ограничитель Регулируемой процентной ставки подсистемы 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: ''