Модульный тест внешнего кода С с MATLAB Coder

В этом примере показано, как протестировать внешний код С с помощью модульных тестов MATLAB ® с Coder™ MATLAB ®.

Если вы хотите протестировать код С, можно использовать MATLAB Coder, чтобы перенести код в MATLAB. Затем можно записать модульные тесты с помощью среды тестирования MATLAB. Можно написать более богатые, гибкие тесты, воспользовавшись расширенными возможностями числовых вычислений и визуализации MATLAB.

В этом примере показано, как:

  1. Внесите Код С в MATLAB как MEX-функцию, которую вы генерируете с MATLAB Coder.

  2. Написание модульного теста с помощью среды тестирования MATLAB.

  3. Запустите тест на 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 строит графики траектории расчетных и фактических положений объекта. Каждый модульный тест вызывает эту функцию.

Сгенерируйте MEX и запустите модульные тесты в приложении MATLAB Coder

Чтобы открыть приложение 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 интегрирует внешний код С

  1. Для типа сборки задайте MEX.

  2. Щелкните Дополнительные параметры.

  3. На вкладке Пользовательский код:

  • В разделе Пользовательский код С для сгенерированных файлов выберите Файл заголовка. В поле пользовательского кода введите #include "kalmanfilter.h".

  • В поле Дополнительные исходные файлы введите kalmanfilter.c.

Чтобы сгенерировать MEX-функцию, нажмите Generate.

Запустите модульные тесты на сгенерированном MEX.

  1. Нажмите «Проверить код».

  2. В поле для тестового файла задайте run_unit_tests_kalman.

  3. Убедитесь, что для параметра «Выполнить с использованием» задано значение «Сгенерированный код».

  4. Щелкните Выполнить сгенерированный код.

Когда приложение запускает тестовый файл, оно заменяет вызовы на callKalmanFilter в модульном тесте с вызовами для callKalmanFilter_mex. Модульные тесты выполняются на MEX-функции вместо исходной функции MATLAB.

Приложение отображает выход теста на вкладке Test Output. Модульные тесты проходят.

На графиках можно увидеть, что траектория предполагаемого положения сходится с траекторией фактического положения.

Запуск модульных тестов после изменения кода С

Когда вы изменяете код С, чтобы запустить модульные тесты:

  1. Перегенерируйте MEX-функцию для функции MATLAB, которая вызывает код С

  2. Повторите верификацию шаг.

Для примера измените kalmanfilter.c так, чтобы значение, присвоенное y[r2] умножается на 1.1.

y[r2] += (double)d_a[r2 + (i0 << 1)] * x_est[i0] * 1.1;

Редактирование kalmanfilter.c вне приложения, поскольку вы можете использовать приложение для редактирования только файлов MATLAB, перечисленных на панели Исходный код приложения.

Чтобы сгенерировать MEX-функцию для измененной функции, нажмите Generate.

Чтобы запустить модульные тесты:

  1. Нажмите «Проверить код».

  2. Убедитесь, что вы установили тестовый файл на run_unit_tests и Запуск с использованием в сгенерированный код

  3. Щелкните Выполнить сгенерированный код.

Не удалось выполнить тесты, поскольку ошибка превышает заданный допуск.

Графики показывают ошибку между траекторией для предполагаемого положения и траекторией для фактического положения.

Сгенерируйте MEX и запустите модульные тесты при помощи рабочего процесса командная строка

Можно использовать рабочий процесс командной строки, чтобы запустить модульные тесты на внешнем коде С при помощи 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.

См. также

Похожие темы