В этом примере показано, как протестировать внешний код С с помощью модульных тестов MATLAB ® с Coder™ MATLAB ®.
Если вы хотите протестировать код С, можно использовать MATLAB Coder, чтобы перенести код в MATLAB. Затем можно записать модульные тесты с помощью среды тестирования MATLAB. Можно написать более богатые, гибкие тесты, воспользовавшись расширенными возможностями числовых вычислений и визуализации MATLAB.
В этом примере показано, как:
Внесите Код С в MATLAB как MEX-функцию, которую вы генерируете с MATLAB Coder.
Написание модульного теста с помощью среды тестирования MATLAB.
Запустите тест на MEX-функции.
Если у вас есть Embedded Coder ®, можно запустить модульные тесты на сгенерированном автономном коде (статическая библиотека или общая библиотека), используя модульные тесты с выполнением ПО в цикле (SIL) или по процессору в цикле (PIL).
Чтобы получить доступ к файлам, которые использует этот пример, нажмите Open Script.
kalmanfilter.c
kalmanfilter.c
- функция C, которую тестирует пример. Он оценивает положение движущегося объекта на основе его прошлых положений.
kalmanfilter.h
kalmanfilter.h
- заголовочный файл для kalmanfilter.c
.
position.mat
position.mat
содержит положения объекта.
callKalmanFilter.m
callKalmanFilter
вызывает kalmanfilter
при помощи coder.ceval
.
function [a,b] = callKalmanFilter(position) % Copyright 2014 - 2016 The MathWorks, Inc. numPts = size(position,2); a = zeros(2,numPts,'double'); b = zeros(2,numPts,'double'); y = zeros(2,1,'double'); % Main loop for idx = 1: numPts z = position(:,idx); % Get the input data % Call the initialize function coder.ceval('kalmanfilter_initialize'); % Call the C function coder.ceval('kalmanfilter',z,coder.ref(y)); % Call the terminate function coder.ceval('kalmanfilter_terminate'); a(:,idx) = [z(1); z(2)]; b(:,idx) = [y(1); y(2)]; end end
TestKalmanFilter.m
TestKalmanFilter
проверяет, превышает ли ошибка между предсказанным положением и фактическим положением заданный допуск. Модульные тесты модульных тестов , основанного на классах. Для получения дополнительной информации см. Создание модульных тестов на основе классов в MATLAB.
Хотя вы хотите протестировать MEX-функцию, модуль тестирует в TestKalmanFilter
вызовите исходную функцию MATLAB, из которой вы сгенерировали MEX-функцию. Когда MATLAB Coder запускает тесты, он заменяет вызовы функции MATLAB вызовами MEX-функции. Вы не можете запустить эти тесты непосредственно в MATLAB, потому что MATLAB не распознает coder.ceval
вызовы в callKalmanFilter
.
classdef TestKalmanFilter < matlab.unittest.TestCase % Copyright 2014 - 2016 The MathWorks, Inc. methods ( Test ) function SSE_LessThanTolerance( testCase ) load position.mat; [z,y] = callKalmanFilter( position ); tolerance = 0.001; % tolerance of 0.0001 will break A = z-1000*y; error = sum(sum(A.^2)); testCase.verifyLessThanOrEqual( error, tolerance); % For debugging plot_kalman_filter_trajectory(z,1000*y); end function SampleErrorLessThanTolerance( testCase ) load position.mat; [z,y] = callKalmanFilter( position ); tolerance = 0.01; % tolerance of 0.001 will break A = z-1000*y; testCase.verifyEqual(1000*y, z, 'AbsTol', tolerance); % For debugging plot_kalman_filter_trajectory(z,1000*y); [value, location] = max(A(:)); [R,C] = ind2sub(size(A),location); disp(['Max value ' num2str(value) ' is located at [' num2str(R) ',' num2str(C) ']']); end end end
run_unit_tests_kalman.m
run_unit_tests_kalman
вызывает runtests
чтобы запустить тесты в TestKalmanFilter.m
.
% Run unit tests % Copyright 2014 - 2016 The MathWorks, Inc. runtests('TestKalmanFilter')
plot_kalman_filter_trajectory.m
plot_kalman_filter_trajectory
строит графики траектории расчетных и фактических положений объекта. Каждый модульный тест вызывает эту функцию.
Чтобы открыть приложение MATLAB Coder, на вкладке MATLAB Toolstrip Apps, в разделе Генерация кода, щелкните значок приложения MATLAB Coder.
Чтобы подготовиться к генерации кода, пройдите по шагам приложения.
На странице Select Source Files задайте, что функция точки входа callKalmanFilter
.
На странице Define Input Types задайте, что входной параметр x
является массив типа double 2 на 310.
Модульные тесты загружают переменную position
от position.mat
и передайте position
на callKalmanFilter
. Поэтому вход для callKalmanFilter
должны иметь свойства, которые position
имеет. В рабочем пространстве MATLAB, если вы загружаете position.mat
, вы видите это position
является массив типа double 2 на 310.
Пропустите шаг Проверка проблем во время выполнения для этого примера.
Настройте приложение для генерации кода MEX. Укажите имена исходных и заголовочных файлов C, поскольку callKalmanFilter
интегрирует внешний код С
Для типа сборки задайте MEX
.
Щелкните Дополнительные параметры.
На вкладке Пользовательский код:
В разделе Пользовательский код С для сгенерированных файлов выберите Файл заголовка. В поле пользовательского кода введите #include "kalmanfilter.h"
.
В поле Дополнительные исходные файлы введите kalmanfilter.c
.
Чтобы сгенерировать MEX-функцию, нажмите Generate.
Запустите модульные тесты на сгенерированном MEX.
Нажмите «Проверить код».
В поле для тестового файла задайте run_unit_tests_kalman
.
Убедитесь, что для параметра «Выполнить с использованием» задано значение «Сгенерированный код».
Щелкните Выполнить сгенерированный код.
Когда приложение запускает тестовый файл, оно заменяет вызовы на callKalmanFilter
в модульном тесте с вызовами для callKalmanFilter_mex
. Модульные тесты выполняются на MEX-функции вместо исходной функции MATLAB.
Приложение отображает выход теста на вкладке Test Output. Модульные тесты проходят.
На графиках можно увидеть, что траектория предполагаемого положения сходится с траекторией фактического положения.
Когда вы изменяете код С, чтобы запустить модульные тесты:
Перегенерируйте MEX-функцию для функции MATLAB, которая вызывает код С
Повторите верификацию шаг.
Для примера измените kalmanfilter.c
так, чтобы значение, присвоенное y[r2]
умножается на 1.1.
y[r2] += (double)d_a[r2 + (i0 << 1)] * x_est[i0] * 1.1;
Редактирование kalmanfilter.c
вне приложения, поскольку вы можете использовать приложение для редактирования только файлов MATLAB, перечисленных на панели Исходный код приложения.
Чтобы сгенерировать MEX-функцию для измененной функции, нажмите Generate.
Чтобы запустить модульные тесты:
Нажмите «Проверить код».
Убедитесь, что вы установили тестовый файл на run_unit_tests
и Запуск с использованием в сгенерированный код
Щелкните Выполнить сгенерированный код.
Не удалось выполнить тесты, поскольку ошибка превышает заданный допуск.
Графики показывают ошибку между траекторией для предполагаемого положения и траекторией для фактического положения.
Можно использовать рабочий процесс командной строки, чтобы запустить модульные тесты на внешнем коде С при помощи coder.runTest
. Укажите тестовый файл, который запускает модульные тесты функции MATLAB, которая вызывает ваш код С
Сгенерируйте MEX-функцию для функции MATLAB, которая вызывает ваш код С В данном примере сгенерируйте MEX для callKalmanFilter
.
Создайте объект строения для генерации кода MEX.
cfg = coder.config('mex');
Укажите внешний исходный код и файл заголовка.
cfg.CustomSource = 'kalmanfilter.c'; cfg.CustomHeaderCode = '#include "kalmanfilter.h"';
Чтобы определить тип входа, который будет callKalmanFilter
, загрузите файл положения.
load position.mat
Чтобы сгенерировать MEX-функцию, запустите codegen
. Задайте, чтобы вход callKalmanFilter
имеет тот же тип, что и position
.
codegen -config cfg callKalmanFilter -args position
Code generation successful.
Запустите модули тесты на MEX-функцию. Укажите, что тестовый файл run_unit_tests_kalman
и что функция callKalmanfilter
. Когда coder.runTest
запускает тестовый файл, он заменяет вызовы на callKalmanFilter
в модульном тесте с вызовами для callKalmanFilter_mex
. Модульные тесты выполняются на MEX-функции вместо исходной функции MATLAB.
coder.runTest('run_unit_tests_kalman', 'callKalmanFilter')
Running TestKalmanFilter Current plot held .Current plot held Max value 0.0010113 is located at [2,273] . Done TestKalmanFilter __________ ans = 1x2 TestResult array with properties: Name Passed Failed Incomplete Duration Details Totals: 2 Passed, 0 Failed, 0 Incomplete. 20.4016 seconds testing time.