diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/hideLeftSidebarPlots.m b/lib/+artoa/+controller/+track/+trajectoryOutput/hideLeftSidebarPlots.m index 09d65dfc1d15586a9785dce513b3bce834b87234..fba43fcc27e5a64f776fca783d62ce7042340857 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/hideLeftSidebarPlots.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/hideLeftSidebarPlots.m @@ -4,10 +4,10 @@ function [] = hideLeftSidebarPlots() global artoaGui; -%% Hide residuals plot -structfun(@delete, artoaGui.trajectoryOutput.residualsHandles); -artoaGui.trajectoryOutput.legendResiduals.Visible = 'off'; -artoaGui.trajectoryOutput.axesTrajectoryResiduals.Visible = 'off'; +%% Hide time divergence plot +structfun(@delete, artoaGui.trajectoryOutput.timeDivergenceHandles); +artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence.Visible = 'off'; +artoaGui.trajectoryOutput.legendTrajectoryTimeDivergence.Visible = 'off'; artoaGui.trajectoryOutput.selectTrajectoryHint.Visible = 'on'; %% Hide velocities plot structfun(@delete, artoaGui.trajectoryOutput.horizontalVelocitiesHandles); @@ -15,7 +15,7 @@ artoaGui.trajectoryOutput.legendHorizontalVelocities.Visible = 'off'; artoaGui.trajectoryOutput.axesHorizontalVelocities.Visible = 'off'; artoaGui.trajectoryOutput.selectTrajectoryHintHorizontalVelocities.Visible = 'on'; %% Hide vertical velocities plot -structfun(@delete, artoaGui.trajectoryOutput.verticalVelocitiesHandles); +%structfun(@delete, artoaGui.trajectoryOutput.verticalVelocitiesHandles); artoaGui.trajectoryOutput.legendVerticalVelocities.Visible = 'off'; artoaGui.trajectoryOutput.axesVerticalVelocities.Visible = 'off'; artoaGui.trajectoryOutput.selectTrajectoryHintVerticalVelocities.Visible = 'on'; diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/showLeftSidebarPlots.m b/lib/+artoa/+controller/+track/+trajectoryOutput/showLeftSidebarPlots.m index 146b217ab35512c0fc8df0bb3585b6f0ecbbeaf1..0e4e587052e5bc212f7c9293405776173f0a8b96 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/showLeftSidebarPlots.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/showLeftSidebarPlots.m @@ -4,9 +4,9 @@ function [] = showLeftSidebarPlots() global artoaGui; -%% Show residuals plot -artoaGui.trajectoryOutput.axesTrajectoryResiduals.Visible = 'on'; -artoaGui.trajectoryOutput.legendResiduals.Visible = 'on'; +%% Show time divergence plot +artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence.Visible = 'on'; +artoaGui.trajectoryOutput.legendTrajectoryTimeDivergence.Visible = 'on'; artoaGui.trajectoryOutput.selectTrajectoryHint.Visible = 'off'; %% Show velocities plot artoaGui.trajectoryOutput.axesHorizontalVelocities.Visible = 'on'; diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/tableGeneratedTracksSelect.m b/lib/+artoa/+controller/+track/+trajectoryOutput/tableGeneratedTracksSelect.m index 00ffa06e66339dbae24c9e731ad69d005a9c1dcc..f6fe69d0642c8387e53075097354dc79cf6c0d8a 100644 --- a/lib/+artoa/+controller/+track/+trajectoryOutput/tableGeneratedTracksSelect.m +++ b/lib/+artoa/+controller/+track/+trajectoryOutput/tableGeneratedTracksSelect.m @@ -52,12 +52,12 @@ artoa.controller.track.trajectoryOutput.emphasizeSelectedTrajectory(); %% Show plots artoa.controller.track.trajectoryOutput.showLeftSidebarPlots(); -%% Plot residuals +%% Plot time divergence [ ... - artoaGui.trajectoryOutput.residualsHandles, ... - artoaGui.trajectoryOutput.legendResiduals ... -] = artoa.trajectory.plotResiduals( ... - artoaGui.trajectoryOutput.axesTrajectoryResiduals, ... + artoaGui.trajectoryOutput.timeDivergenceHandles, ... + artoaGui.trajectoryOutput.legendTrajectoryTimeDivergence ... +] = artoa.trajectory.plotTimeDivergenceToGps( ... + artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence, ... artoaWorkspace.trajectoryOutput.trajectories{selectedRow(1)} ... ); @@ -71,13 +71,6 @@ artoa.controller.track.trajectoryOutput.showLeftSidebarPlots(); ); %% Plot vertical velocities -[ ... - artoaGui.trajectoryOutput.verticalVelocitiesHandles, ... - artoaGui.trajectoryOutput.legendVerticalVelocities ... -] = artoa.trajectory.plotVerticalVelocities( ... - artoaGui.trajectoryOutput.axesVerticalVelocities, ... - artoaWorkspace.trajectoryOutput.trajectories{selectedRow} ... -); %% Replace track parameter if artoaWorkspace.trajectoryOutput.updateTrackParameterWindow diff --git a/lib/+artoa/+controller/+track/run.m b/lib/+artoa/+controller/+track/run.m index 247ae5a6120e0b1f1eb3bc44cbe95b06276fdb39..04a2e019f00945b7cf3b121d78059c086c8d4fda 100644 --- a/lib/+artoa/+controller/+track/run.m +++ b/lib/+artoa/+controller/+track/run.m @@ -68,10 +68,12 @@ pressureAndDate = { ... trajectoryDates, ... trajectoryClockError, ... trajectoryResiduals, ... - trajectoryVelocities ... + trajectoryVelocities, ... + trajectoryTimeDivergenceToGps ... ] = artoa.float.calculateTrajectory( ... artoaWorkspace.float, ... pressureAndDate, ... + artoaWorkspace.satData, ... artoaWorkspace.toaData, ... artoaWorkspace.filteredSoundsources, ... artoaWorkspace.trackParameter, ... @@ -100,6 +102,7 @@ trajectoryObject.date = trajectoryDates; trajectoryObject.clockError = trajectoryClockError; trajectoryObject.residuals = trajectoryResiduals; trajectoryObject.velocities = trajectoryVelocities; +trajectoryObject.timeDivergenceToGps = trajectoryTimeDivergenceToGps; %% Generate trajectory id if isempty(artoaWorkspace.trajectoryOutput.trajectories) diff --git a/lib/+artoa/+data/calculateTimeDivergence.m b/lib/+artoa/+data/calculateTimeDivergence.m new file mode 100644 index 0000000000000000000000000000000000000000..77c8026a66bd656f82782d0b362febeaa1ce0dc5 --- /dev/null +++ b/lib/+artoa/+data/calculateTimeDivergence.m @@ -0,0 +1,31 @@ +function [timeDivergence, usedIndices] = calculateTimeDivergence(pPositionSet1, pPositionSet2, pSoundVelocity) +%CALCULATETIMEDIVERGENCE Summary of this function goes here +% Detailed explanation goes here + +%% Setup variables +timeDivergence = []; +usedIndices = []; + +%% Parameter check +if isempty(pPositionSet1) || isempty(pPositionSet2) + return; +end +%% Calculate distance between sets +for i = 1:size(pPositionSet1, 1) + if any(isnan(pPositionSet1(i, :))) || any(isnan(pPositionSet2(i, :))) + usedIndices = [usedIndices; false]; + continue; + end + timeDivergence = [ + timeDivergence; ... + artoa.data.calculateGeodist(pPositionSet1(i, :), pPositionSet2(i, :)) ... + ]; + usedIndices = [usedIndices; true]; +end + +%% Divide by sound velocity +timeDivergence = timeDivergence / (pSoundVelocity/1000); +usedIndices = logical(usedIndices); + +end + diff --git a/lib/+artoa/+float/calculateTrajectory.m b/lib/+artoa/+float/calculateTrajectory.m index c4971c1ace2b5d0a915549fd21541ed5345ad54c..e837eecf1fd1aa954c490896b8470dc4ac3395d3 100644 --- a/lib/+artoa/+float/calculateTrajectory.m +++ b/lib/+artoa/+float/calculateTrajectory.m @@ -1,4 +1,4 @@ -function [trajectory, trajectoryDates, trajectoryClockError, trajectoryResiduals, trajectoryVelocities] = calculateTrajectory(pFloatDetails, pPressureAndDate, pToaData, pSoundsources, pTrackingParameter, pSoundVelocity, pLeapsecondsMatrix) +function [trajectory, trajectoryDates, trajectoryClockError, trajectoryResiduals, trajectoryVelocities, trajectoryTimeDivergenceToGps] = calculateTrajectory(pFloatDetails, pPressureAndDate, pSatData, pToaData, pSoundsources, pTrackingParameter, pSoundVelocity, pLeapsecondsMatrix) %CALCULATETRAJECTORY Calculates the trajectory using the given details. % Applies all required corrections to the data and calculates the trajectory % segment by segment afterwards. @@ -204,14 +204,19 @@ trajectory = []; trajectoryDates = []; trajectoryClockError = []; trajectoryResiduals = struct(); +trajectoryTimeDivergenceToGps = struct(); for i = 1:length(involvedSoundsourceNames) trajectoryResiduals.(involvedSoundsourceNames{i}) = []; + trajectoryTimeDivergenceToGps.(involvedSoundsourceNames{i}) = []; end trajectoryVelocities = struct(); trajectoryVelocities.horizontalTotal = []; trajectoryVelocities.horizontalLongitude = []; trajectoryVelocities.horizontalLatitude = []; trajectoryVelocities.vertical = []; +% trajectoryTimeDivergenceToGps = struct(); +% trajectoryTimeDivergenceToGps.duration = []; +% trajectoryTimeDivergenceToGps.date = []; %% Calculate for every combination for oCombination = 1:size(soundsourceCombinations, 1) @@ -255,7 +260,11 @@ for oCombination = 1:size(soundsourceCombinations, 1) end % calculate horizontal velocities - [segmentHorizontalVelocityTotal, segmentHorizontalVelocityLatitude, segmentHorizontalVelocityLongitude] = artoa.data.horvelo( ... + [ ... + segmentHorizontalVelocityTotal, ... + segmentHorizontalVelocityLatitude, ... + segmentHorizontalVelocityLongitude ... + ] = artoa.data.horvelo( ... segmentPositions(:, 1), ... segmentPositions(:, 2), ... pTrackingParameter.interpolationInterval/24*86400 ... @@ -272,6 +281,42 @@ for oCombination = 1:size(soundsourceCombinations, 1) 'average' ... ); trajectoryVelocities.vertical = [trajectoryVelocities.vertical; segmentVerticalVelocity]; + + % calculate time divergence to gps + % get all sat dates + satDates = artoa.convert.dmy2rd(pSatData.day_sat, pSatData.month_sat, pSatData.year_sat); + % get all dates that intersect with segment + [~, index, ~] = intersect(round(segmentDates), round(satDates)); + intersectedSegmentPositions = segmentPositions(index, :); + intersectedSegmentDates = segmentDates(index, :); + satPositions = [pSatData.lat_sat(index), pSatData.lon_sat(index)]; + % get all soundsources of segment + segmentSoundsources = artoa.data.extractSoundsourcesFromStruct( ... + strsplit(soundsourceCombinations.soundsources{oCombination}), ... + pSoundsources ... + ); + for oSoundsource = 1:length(segmentSoundsources) + currentSoundsource = segmentSoundsources{oSoundsource}; + % calculate divergence for soundsource position + [soundsourceDivergence, ~] = artoa.data.calculateTimeDivergence( ... + repmat(currentSoundsource.position, size(intersectedSegmentPositions, 1), 1), ... + intersectedSegmentPositions, ... + pSoundVelocity(oCombination, oSoundsource) ... + ); + [gpsDivergence, usedIndices] = artoa.data.calculateTimeDivergence( ... + repmat(currentSoundsource.position, size(satPositions, 1), 1), ... + satPositions, ... + pSoundVelocity(oCombination, oSoundsource) ... + ); + if isempty(usedIndices) || isempty(soundsourceDivergence) || isempty(gpsDivergence) + continue; + end + difference = (soundsourceDivergence(usedIndices) - gpsDivergence); + trajectoryTimeDivergenceToGps.(currentSoundsource.sourcename) = [ ... + trajectoryTimeDivergenceToGps.(currentSoundsource.sourcename); + segmentDates(usedIndices), difference + ]; + end end -return \ No newline at end of file +end \ No newline at end of file diff --git a/lib/+artoa/+gui/+track/trajectoryOutput.m b/lib/+artoa/+gui/+track/trajectoryOutput.m index b8ce3415755c214fcecfbdebb090d2e33fd123a7..b24bff48ea6c9337c701b53df89eb1d80301f0dc 100644 --- a/lib/+artoa/+gui/+track/trajectoryOutput.m +++ b/lib/+artoa/+gui/+track/trajectoryOutput.m @@ -77,25 +77,25 @@ artoaGui.trajectoryOutput.axesTrajectoryOutput = artoaGui.figures.trajectoryOutp %% Left sidebar -%% Residuals +%% Time divergence to GPS -artoaGui.trajectoryOutput.frameAxesResiduals = uipanel( ... - 'Title', 'Residuals', ... +artoaGui.trajectoryOutput.frameAxesTimeDivergence = uipanel( ... + 'Title', 'Time divergence to GPS', ... 'Units', 'normalized', ... 'BackgroundColor', 'white', ... 'Position', [leftSidebarLeft, .675, leftSidebarWidth, .3] ... ); -artoaGui.trajectoryOutput.axesTrajectoryResiduals = axes(artoaGui.trajectoryOutput.frameAxesResiduals); -artoaGui.trajectoryOutput.axesTrajectoryResiduals.Position = [.15 .15 .8 .8]; -xlabel(artoaGui.trajectoryOutput.axesTrajectoryResiduals, 'Message Date'); -ylabel(artoaGui.trajectoryOutput.axesTrajectoryResiduals, 'TOA residuals [s]'); -grid(artoaGui.trajectoryOutput.axesTrajectoryResiduals, 'on'); -artoaGui.trajectoryOutput.axesTrajectoryResiduals.Visible = 'off'; +artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence = axes(artoaGui.trajectoryOutput.frameAxesTimeDivergence); +artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence.Position = [.15 .15 .8 .8]; +xlabel(artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence, 'Message Date'); +ylabel(artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence, 'Time divergence [s]'); +grid(artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence, 'on'); +artoaGui.trajectoryOutput.axesTrajectoryTimeDivergence.Visible = 'off'; % Setup hint to select trajectory artoaGui.trajectoryOutput.selectTrajectoryHint = uicontrol( ... - 'Parent', artoaGui.trajectoryOutput.frameAxesResiduals, ... + 'Parent', artoaGui.trajectoryOutput.frameAxesTimeDivergence, ... 'Style', 'text', ... 'String', 'No trajectory selected', ... 'FontSize', 8, ... diff --git a/lib/+artoa/+trajectory/plotTimeDivergenceToGps.m b/lib/+artoa/+trajectory/plotTimeDivergenceToGps.m new file mode 100644 index 0000000000000000000000000000000000000000..9813f6cc759a723f66f46daa9e4accaccde8927c --- /dev/null +++ b/lib/+artoa/+trajectory/plotTimeDivergenceToGps.m @@ -0,0 +1,30 @@ +function [handleTimeDivergenceToGps, handleLegend] = plotTimeDivergenceToGps(pAxesHandle, pTrajectory) +%PLOTTIMEDIVERGENCETOGPS Summary of this function goes here +% Detailed explanation goes here + +%% Setup return variables +handleTimeDivergenceToGps = struct(); + +%% Get required data +fnames = fieldnames(pTrajectory.timeDivergenceToGps); +legendText = {}; + +%% Clear axes +cla(pAxesHandle); + +%% Plot data +hold(pAxesHandle, 'on'); +for i = 1:length(fnames) + current = pTrajectory.timeDivergenceToGps.(fnames{i}); + x = current(:, 1); + y = current(:, 2); + handleTimeDivergenceToGps.(fnames{i}) = plot(pAxesHandle, x, y, '.-'); + legendText{i} = fnames{i}; +end +hold(pAxesHandle, 'off'); + +%% Setup legend +handleLegend = legend(pAxesHandle, legendText); + +end +