Skip to content
Snippets Groups Projects
Commit 1dff61a4 authored by leprob001's avatar leprob001
Browse files

Added offsets calculation using matrix A, B, X.

parent d2e448b0
No related branches found
No related tags found
No related merge requests found
function [] = buttonCalculateOffsets(~, ~)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
global artoaWorkspace artoaDataInput;
%% Initialize required variables
soundsources = artoa.controller.getSoundsourcesWithAppliedToa();
satData = artoaWorkspace.satData;
%% Calculate offsets
[
artoaWorkspace.editOffsets.calculatedMatrixA, ...
artoaWorkspace.editOffsets.calculatedMatrixB, ...
artoaWorkspace.editOffsets.calculatedMatrixX ...
] = artoa.offsets.solve( ...
artoaDataInput.rfb, ...
soundsources, ...
satData, ...
artoaWorkspace.temperature(artoaWorkspace.statusTemperature == 1), ...
artoaWorkspace.pressure(artoaWorkspace.statusPressure == 1), ...
artoaWorkspace.trackParameter.soundspeedMethodString, ...
artoa.data.getMember(artoaDataInput, {'ini', 'leapseconds'}) ...
);
%% Store offsets in table
[offsets, drifts] = artoa.offsets.extractOffsetsDriftsFromSolved(artoaWorkspace.editOffsets.calculatedMatrixX);
artoaWorkspace.editOffsets.soundsourceOffsets.OptimumTotalOffset = offsets;
artoaWorkspace.editOffsets.soundsourceOffsets.OptimumTotalDrift = drifts;
%% Update TOA
% combine initial toa and current applied soundsources
toaData = artoaWorkspace.toaData;
toaData.toa = artoaDataInput.toaData.toa;
%% Recalculate drift
artoa.controller.edit.offsets.updateWorkspaceOffsetsTable();
artoa.controller.edit.offsets.updateGui();
%% Select offset and drift from the table
artoa.controller.edit.offsets.selectOffsetsAndDrift();
artoaWorkspace.toaData = artoa.toa.recalculate( ...
artoaWorkspace.float, ...
toaData, ...
artoa.controller.getSoundsourcesWithAppliedToa(), ...
artoaWorkspace.editOffsets.selectedOffsets ...
);
artoa.controller.edit.timeOfArrival.plot();
end
function [newValue] = checkboxForceOptimumOffsets(~, ~)
%CHECKBOXDOPPLERCORRECTION Summary of this function goes here
% Detailed explanation goes here
global artoaGui artoaWorkspace artoaDataInput;
newValue = logical(artoaGui.editOffsets.checkboxForceOptimumOffsets.Value);
artoaWorkspace.editOffsets.forceOptimumOffsets = newValue;
%% Update TOA
% combine initial toa and current applied soundsources
toaData = artoaWorkspace.toaData;
toaData.toa = artoaDataInput.toaData.toa;
%% Recalculate drift
artoa.controller.edit.offsets.updateWorkspaceOffsetsTable();
artoa.controller.edit.offsets.updateGui();
%% Select offset and drift from the table
artoa.controller.edit.offsets.selectOffsetsAndDrift();
artoaWorkspace.toaData = artoa.toa.recalculate( ...
artoaWorkspace.float, ...
toaData, ...
artoa.controller.getSoundsourcesWithAppliedToa(), ...
artoaWorkspace.editOffsets.selectedOffsets ...
);
artoa.controller.edit.timeOfArrival.plot();
end
......@@ -15,6 +15,8 @@ end
callbacks = struct();
callbacks.tableSoundsourceOffsetsEdit = @artoa.controller.edit.offsets.tableSoundsourceOffsetsEdit;
callbacks.buttonCalculateOffsets = @artoa.controller.edit.offsets.buttonCalculateOffsets;
callbacks.checkboxForceOptimumOffsets = @artoa.controller.edit.offsets.checkboxForceOptimumOffsets;
%% Open the gui
artoa.gui.edit.offsets(callbacks);
......@@ -26,6 +28,7 @@ end
%% Create workspace variables
artoaWorkspace.editOffsets = struct();
artoaWorkspace.editOffsets.forceOptimumOffsets = false;
artoa.controller.edit.offsets.updateWorkspaceOffsetsTable();
%% Update gui
......
......@@ -10,8 +10,16 @@ selectedOffsets = table();
%% Get required variables
offsetsTable = artoaWorkspace.editOffsets.soundsourceOffsets;
%% Select float offset and drift;
selectedOffsets('Float', :) = selectFromRow(offsetsTable('Float', :));
%% Select float offset and drift
if artoaWorkspace.editOffsets.forceOptimumOffsets
tmp = table();
tmp.offset = offsetsTable{'Float', 'OptimumTotalOffset'};
tmp.drift = offsetsTable{'Float', 'OptimumTotalDrift'};
selectedOffsets('Float', :) = tmp;
clear tmp;
else
selectedOffsets('Float', :) = selectFromRow(offsetsTable('Float', :));
end
%% Run through all soundsources
variableNames = offsetsTable.Properties.RowNames;
......@@ -19,7 +27,15 @@ for i = 1:length(variableNames)
if strcmp('Float', variableNames{i})
continue;
end
selectedOffsets(variableNames{i}, :) = selectFromRow(offsetsTable(variableNames{i}, :));
if artoaWorkspace.editOffsets.forceOptimumOffsets
tmp = table();
tmp.offset = offsetsTable{variableNames{i}, 'OptimumTotalOffset'};
tmp.drift = offsetsTable{variableNames{i}, 'OptimumTotalDrift'};
selectedOffsets(variableNames{i}, :) = tmp;
clear tmp;
else
selectedOffsets(variableNames{i}, :) = selectFromRow(offsetsTable(variableNames{i}, :));
end
end
%% Store selected values
......
......@@ -16,6 +16,8 @@ fieldNames = fieldnames(fields);
for i = 1:length(fieldNames)
currentValue = fields.(fieldNames{i});
switch fieldNames{i}
case 'forceOptimumOffsets'
artoaGui.editOffsets.checkboxForceOptimumOffsets.Value = currentValue;
case 'soundsourceOffsets'
artoaGui.editOffsets.tableSoundsourceOffsets.Data = table2cell( ...
currentValue ...
......
......@@ -6,7 +6,6 @@ function [calculatedSoundVelocity] = calculateSoundVelocity(pTemperature, pPress
% pMethod The chosen method. Available methods are:
% del grosso
% linear
% soundsource
%
% Returns:
% The calculated sound velocity in m/s.
......
......@@ -12,7 +12,9 @@ windowTitle = [ 'ARTOA4 - Float ' num2str(artoaWorkspace.float.floatname) ' - Of
availableCallbacks = { ...
'CloseRequestFcn', ...
'tableSoundsourceOffsetsSelect', ...
'tableSoundsourceOffsetsEdit' ...
'tableSoundsourceOffsetsEdit', ...
'buttonCalculateOffsets', ...
'checkboxForceOptimumOffsets' ...
};
for i = 1:length(availableCallbacks) % check if a callback is undefined
......@@ -56,6 +58,35 @@ artoaGui.editOffsets.tableSoundsourceOffsets = uitable( ...
'CellEditCallback', pCallbacks.tableSoundsourceOffsetsEdit ...
);
%% Optimum offsets frame
artoaGui.editOffsets.frameOptimumOffsets = uipanel( ...
'Title', 'Offset controls', ...
'Units', 'normalized', ...
'BackgroundColor', 'white', ...
'Position', [left .05 fullwidth/2 .35] ...
);
%% Setup calculate offsets button
artoaGui.editOffsets.buttonCalculateOffsets = uicontrol( ...
'Parent', artoaGui.editOffsets.frameOptimumOffsets, ...
'String', 'Calculate offsets', ...
'Style', 'PushButton', ...
'FontSize', 8, ...
'Units', 'normalized', ...
'Position', [.65 .1 .25 .2], ...
'CallBack', pCallbacks.buttonCalculateOffsets ...
);
artoaGui.editOffsets.checkboxForceOptimumOffsets = uicontrol( ...
'Parent', artoaGui.editOffsets.frameOptimumOffsets, ...
'String', 'Force using optimum offsets', ...
'Style', 'checkbox', ...
'FontSize', 8, ...
'Units', 'normalized', ...
'Position', [left .75 fullwidth/2 .2], ...
'CallBack', pCallbacks.checkboxForceOptimumOffsets ...
);
end
function [offsets, drifts] = extractOffsetsDriftsFromSolved(pX)
%EXTRACTOFFSETSDRIFTSFROMSOLVED Summary of this function goes here
% Detailed explanation goes here
soundsourceCount = (length(pX) - 4) / 2;
offsets = NaN(soundsourceCount + 1, 1);
drifts = NaN(soundsourceCount + 1, 1);
offsets(1) = pX(end - 1);
drifts(1) = pX(end);
for i = 2:soundsourceCount + 1
startIndex = (i - 1) * 2 + 3;
offsets(i) = pX(startIndex);
drifts(i) = pX(startIndex + 1);
end
end
function [a, b, x] = solve(pRfb, pSoundsources, pSatData, pAppliedTemperature, pAppliedPressure, pSoundspeedMethod, pLeapsecondsMatrix)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
%% Initialize required variables
%pSoundsources = artoa.controller.getSoundsourcesWithAppliedToa();
satPositions = [pSatData.lat_sat, pSatData.lon_sat];
satDates = artoa.convert.dmy2rd(pSatData.day_sat, pSatData.month_sat, pSatData.year_sat);
toaDates = [];
satToas = [];
satDistances = [];
floatDetails = pRfb.FLOAT;
%% Create table
results = struct();
%% Calculate SAT TOAs for every soundsource
fnames = fieldnames(pSoundsources);
for i = 1:length(fnames)
results.(fnames{i}) = table();
[date, toa] = artoa.toa.predictFromGps( ...
pRfb, ...
pSoundsources.(fnames{i}), ...
struct( ...
'temperature', pAppliedTemperature, ...
'pressure', pAppliedPressure, ...
'method', pSoundspeedMethod, ...
'soundSource', NaN ...
), ...
pLeapsecondsMatrix ...
);
results.(fnames{i}).satDate = date;
results.(fnames{i}).satToa = toa;
results.(fnames{i}).daysSinceStart = ...
date ...
- artoa.convert.dmy2rd( ...
pSoundsources.(fnames{i}).begemis(3), ...
pSoundsources.(fnames{i}).begemis(2), ...
pSoundsources.(fnames{i}).begemis(1) ...
);
tmpDistances = [];
% calculate distances
for oDistance = 1:length(toa)
if isnan(toa(oDistance)) | any(isnan(satPositions(oDistance, :)))
tmpDistances = [tmpDistances; NaN];
continue;
end
tmpDistances = [ ...
tmpDistances; ...
artoa.data.calculateGeodist( ...
satPositions(oDistance, :), ...
pSoundsources.(fnames{i}).position ...
) ...
];
end
results.(fnames{i}).satDistances = tmpDistances;
clear tmpDistances;
end
%% Construct matrices A and B
rowCount = length(satDates) * length(fnames);
aCore = zeros(rowCount, 2 * length(fnames));
b = zeros(rowCount, 1);
distances = zeros(rowCount, 1);
daysSinceFloatStart = NaN(rowCount, 1);
soundVelocity = NaN(rowCount, 1);
soundVelocity(:) = artoa.data.calculateSoundVelocity( ...
pAppliedTemperature, ...
pAppliedPressure, ...
pSoundspeedMethod ...
);
for i = 1:length(fnames)
rowIndices = ((i - 1) * length(satDates) + 1):i * length(satDates);
startColIndex = (2 * (i - 1)) + 1;
distances(rowIndices, 1) = results.(fnames{i}).satDistances;
aCore(rowIndices, startColIndex) = 1;
aCore(rowIndices, startColIndex + 1) = results.(fnames{i}).daysSinceStart;
b(rowIndices, 1) = results.(fnames{i}).satToa;
daysSinceFloatStart(rowIndices, 1) = ...
results.(fnames{i}).satDate ...
- artoa.convert.dmy2rd( ...
floatDetails.launchtime(3), ...
floatDetails.launchtime(2), ...
floatDetails.launchtime(1) ...
);
end
a = [ ...
soundVelocity, distances, aCore, ones(size(daysSinceFloatStart)), daysSinceFloatStart ...
];
% remove all NaN from matrix
indicesToUse = all(~isnan(a), 2) & all(aCore >= 0, 2);
%x = a(indicesToUse, :) * flipud(b(indicesToUse, :));
x = pinv(a(indicesToUse, :)) * b(indicesToUse, :);
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment