Skip to content
Snippets Groups Projects
Circular.m 2.86 KiB
function [positions, clockError] = Circular(pData, pSoundsourcePositions, pCombinationDetails, pStartEndPosition)
%HYPERBOLIC Hyperbolic tracking algorithm. Requires three soundsources.
%
%   Parameters:
%       pData (struct):
%           Data structured by soundsource. The toa is already corrected
%           (e.g. doppler correction etc.)
%       pSoundsourcePositions (struct):
%           The soundsource positions [deg].
%       pCombinationDetails (table):
%           Contains all information of the current soundsource
%           combination.
%       pStartEndPosition (double, logical):
%           Set to false if it has not been passed by artoa. Contains the
%           desired start and end position as a matrix of row vectors.
%
%
%   Returns:
%       positions (double):
%           The calculated list of segment positions as a X x 2 column vector.
%       clockError (double):
%           The estimated clock error.

%% Get reference position and all soundsource names that are involved
referencePosition = cellfun(@str2double, strsplit(pCombinationDetails.referencePosition{1}));
soundsourceNames = strsplit(pCombinationDetails.soundsources{1});

% %% Check if three soundsources are available
% if length(soundsourceNames) ~= 3
%     errordlg(['Hyperbolic tracking algorithm requires three soundsources. ' num2str(length(soundsourceNames)) ' selected!']);
%     error(['Hyperbolic tracking algorithm requires three soundsources. ' num2str(length(soundsourceNames)) ' selected!']);
% end

%% Prepare data for calculations
% get a date vector (does not matter which one)
dates = cell2mat(pData.(soundsourceNames{1}).date);
pDistances = NaN(length(dates), length(soundsourceNames));
soundsourcePositions = NaN(length(soundsourceNames), 2);
soundVelocity = NaN(length(soundsourceNames), 1);
% prepare distances to, and positions of, all soundsources
for oSoundsource = 1:length(soundsourceNames)
    pDistances(:, oSoundsource) = ...
        cell2mat(pData.(soundsourceNames{oSoundsource}).distance);
    soundsourcePositions(oSoundsource, :) = ...
        pSoundsourcePositions.(soundsourceNames{oSoundsource});
    soundVelocity(oSoundsource) = pData.(soundsourceNames{oSoundsource}).soundspeed{1};
end

% initialize return variables
positions = referencePosition;
clockError = [];

% Calculate the actual segment positions
for oDates = 1:length(dates)
    distances = pDistances(oDates, :);
    if any(isnan(distances))
        positions = [positions; [NaN NaN]];
        clockError = [clockError; NaN(1, 3)];
        continue;
    end
    positions = [positions; ...
        rad2deg(artoa.vendor.xnavai(deg2rad(soundsourcePositions), distances, deg2rad(referencePosition), 2)) ...
    ];
    clockError = [clockError; NaN(1, 3)];
    disp([' *** Date: ' num2str(dates(oDates)) ' converged at position: ' num2str(positions(end, 1)) ', ' num2str(positions(end, 2))]);
end

positions = positions(2:end, :);

end