Как сгенерировать код С для трекера

В этом примере показано, как сгенерировать код С для функции MATLAB, которая обрабатывает обнаружения и выводит треки. Функция содержит trackerGNN, но вместо этого можно использовать любой трекер.

Автоматическая генерация кода из кода MATLAB имеет два ключевых преимущества:

  1. Прототипы могут разрабатываться и отлаживаться в среде MATLAB. После выполнения работы MATLAB автоматическая генерация кода C делает алгоритмы развертываемыми для различных целей. Кроме того, код С может быть дополнительно протестирован путем запуска скомпилированного файла MEX в среде MATLAB с помощью тех же инструментов визуализации и анализа, которые были доступны во время фазы прототипирования.

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

Пример объясняет, как изменить код MATLAB в примере Air Traffic Control для поддержки генерации кода. Этот пример требует лицензии MATLAB Coder для генерации кода С

Изменение и запуск кода MATLAB

Чтобы сгенерировать код С, MATLAB Coder требует, чтобы код MATLAB был в форме функции. Кроме того, аргументы функции не могут быть классами MATLAB.

В этом примере код для примера управления воздушным движением (ATC) был реструктурирован так, что trackerGNN который выполняет слияние датчиков и отслеживание находится в отдельном файле, называемом tracker_kernel.m. Проверьте этот файл для получения важной информации о выделении памяти для генерации кода.

Чтобы сохранить состояние trackerGNN между вызовами в tracker_kernel.m, трекер определяется как persistent переменная.

Эта функция принимает массив ячеек objectDetection объекты, сгенерированные fusionRadarSensor объект и время как входные параметры.

Точно так же выходы от функции, которая поддерживает генерацию кода, не могут быть объектами. Выходы tracker_kernel.m являются:

  1. Подтвержденные треки - A struct массив, который содержит переменное количество дорожек.

  2. Количество треков - Целочисленный скаляр.

  3. Информация об обработке трекера при текущем обновлении.

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

% If a previous tracker is defined, clear it.
clear tracker_kernel

% Create the ATC scene with radar and platforms.
[scenario,tower,radar] = helperCreateATCScenario;

% Create a display to show the true, measured, and tracked positions of the
% airliners.
[theater,fig] = helperTrackerCGExample('Create Display',scenario);
helperTrackerCGExample('Update Display',theater,scenario,tower);

Теперь запустите пример, вызвав tracker_kernel функция в MATLAB. Этот начальный запуск предоставляет базовую линию для сравнения результатов и позволяет вам собрать некоторые метрики о эффективности трекера, когда он запускается в MATLAB или как файл MEX.

Моделирование и отслеживание лайнеров

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

% Set simulation to advance at the update rate of the radar.
scenario.UpdateRate = radar.UpdateRate;

% Create a buffer to collect the detections from a full scan of the radar.
scanBuffer = {};

% Initialize the track array.
tracks = [];

% Set random seed for repeatable results.
rng(2020)

% Allocate memory for number of tracks and time measurement in MATLAB.
numSteps  = 12;
numTracks = zeros(1, numSteps);
runTimes  = zeros(1, numSteps);
index = 0;
while advance(scenario) && ishghandle(fig)

    % Generate detections on targets in the radar's current field of view.
    [dets,config] = detect(scenario);

    scanBuffer = [scanBuffer;dets]; %#ok<AGROW> Allow the buffer to grow.

    % Update tracks when a 360 degree scan is complete.
    if config.IsScanDone
        % Update tracker
        index = index + 1;
        tic
        [tracks, numTracks(index), info] = tracker_kernel(scanBuffer,scenario.SimulationTime);
        runTimes(index) = toc; % Gather MATLAB run time data

        % Clear scan buffer for next scan.
        scanBuffer = {};
    end

    % Update display with current beam position, buffered detections, and
    % track positions.
    helperTrackerCGExample('Update Display',theater,scenario,tower,scanBuffer,tracks);
end

Скомпилируйте функцию MATLAB в файл MEX

Используйте codegen функция для компиляции tracker_kernel функция в файл MEX. Можно задать -report опция, чтобы сгенерировать отчет компиляции, который показывает оригинальный код MATLAB и связанные файлы, которые были созданы во время генерации кода C. Рассмотрите создание временной директории, в котором MATLAB Coder может хранить сгенерированные файлы. Обратите внимание, что если вы не используете -o опция, чтобы задать имя исполняемого файла, сгенерированный файл MEX имеет то же имя, что и исходный файл MATLAB с _mex приложенный.

MATLAB Coder требует, чтобы вы задали свойства всех входных параметров. Входы используются трекером для создания правильных типов данных и размеров для объектов, используемых в отслеживании. Типы и размеры данных не должны меняться между системами координат данных. Один из простых способов сделать это - задать входные свойства путем примера в командной строке с помощью -args опция. Для получения дополнительной информации смотрите Входную спецификацию (MATLAB Coder).

% Define the properties of the input. First define the detections buffer as
% a variable-sized cell array that contains objectDetection objects. Then
% define the second argument as simTime, which is a scalar double.
dets = coder.typeof(scanBuffer(1), [inf 1], [1 0]);
compInputs  = {dets scenario.SimulationTime};

% Code generation may take some time.
h = msgbox({'Generating code. This may take a few minutes...';'This message box will close when done.'},'Codegen Message');
% Generate code.
try
    codegen tracker_kernel -args compInputs;
    close(h)
catch ME
    close(h)
    delete(videoDisplayHandle.Parent.Parent)
    throw(ME)
end
Code generation successful.

Запуск сгенерированного кода

Теперь, когда код был сгенерирован, запустите точно такой же сценарий с сгенерированным файлом MEX tracker_kernel_mex. Все остальное остается прежним.

% If a previous tracker is defined, clear it.
clear tracker_kernel_mex

% Allocate memory for number of tracks and time measurement
numTracksMex = zeros(1, numSteps);
runTimesMex  = zeros(1, numSteps);

% Reset the scenario, data counter, plotters, scanBuffer, tracks, and rng.
index = 0;
restart(scenario)
scanBuffer = {};
clearPlotterData(theater);
tracks = [];
rng(2020)
while advance(scenario) && ishghandle(fig)

    % Generate detections on targets in the radar's current field of view.
    [dets,config] = detect(scenario);

    scanBuffer = [scanBuffer;dets]; %#ok<AGROW> Allow the buffer to grow.

    % Update tracks when a 360 degree scan is complete.
    if config.IsScanDone
        % Update tracker.
        index = index + 1;
        tic
        [tracks, numTracksMex(index), info] = tracker_kernel_mex(scanBuffer,scenario.SimulationTime);
        runTimesMex(index) = toc; % Gather MEX run time data

        % Clear scan buffer for next scan.
        scanBuffer = {};
    end

    % Update display with current beam position, buffered detections, and
    % track positions.
    helperTrackerCGExample('Update Display',theater,scenario,tower,scanBuffer,tracks);
end

Сравнение результатов двух запусков

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

figure(2)
subplot(2,1,1)
plot(2:numSteps, numTracks(2:numSteps), 's:', 2:numSteps, numTracksMex(2:numSteps), 'x-.')
title('Number of Tracks at Each Step');
legend('MATLAB', 'MEX')
grid
subplot(2,1,2)
plot(2:numSteps, runTimesMex(2:numSteps)*1e3);
title('MEX Processing Time at Each Step')
grid
xlabel('Time Step')
ylabel('MEX Processing Time [ms]')

Верхний график показывает, что количество треков, которые поддерживались каждым трекером, одинаковое. Он измеряет размер задачи отслеживания с точки зрения количества треков. Даже при наличии 3 подтвержденных дорожек на протяжении всего примера отслеживания, общее количество всех дорожек, поддерживаемых трекером, изменяется на основе количества предварительных дорожек, которые были созданы ложными обнаружениями.

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

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

Сводные данные

Этот пример показал, как сгенерировать код С из кода MATLAB для слияния датчиков и отслеживания.

Основными преимуществами автоматической генерации кода являются возможность прототипа в среде MATLAB и генерации файла MEX, который может запускаться в среде MATLAB. Сгенерированный код C может быть развернут на целевой объект. В большинстве случаев сгенерированный код быстрее, чем код MATLAB, и может использоваться для пакетной проверки алгоритмов и генерации систем отслеживания в реальном времени.