Loop and Cross for Pulse 75

P. McGill
7Feb22

Deployment

Find the Rover and SES locations from ranges obtained by Kent’s new Loop and Cross code on the Wave Glider on 2Feb22 during Pulse 75.

The range of the target as detected by the Wave Glider is the straight-line (Euclidean) distance from the Wave Glider’s location on the surface to the target’s lat, lon, and depth on the sea bottom. Define a function to find the mean squared error between a proposed lat, lon, and depth, and all the ranges and Wave Glider positions given in a list of ranging hits. Locations are given as east, north, up (ENU) units.

locDepthErrorENU[hitList_,target_,depth_]:=
Sum[
((EuclideanDistance[ (* find the distance between... *)
Append[hitList[[k,1]],0], (* the Wave Glider position on surface *)
Append[target,depth] (* and proposed target position and depth *)
] (* subtract the measured range and square the result *)
-hitList[[k,2]])^2), 
{k,1,Length[hitList]} (* iterate over the whole list *)
]/Length[hitList] (* find the mean *)

Import the Rover ranging data.

rawDatRvr=(* Import["/Users/mcgill/Documents/My\ Projects/Pelagic-Benthic\ Coupling/Pulse\ 75/lc-rangeutm-20220204-combined.csv","CSV"]; *)
Import["/Volumes/ProjectLibrary/900502.BenthicRover/Rover.Deployment/Pulse_75/Rover\ Geolocation/lc-rangeutm-20220204-combined.csv"];

The column labels are in the first row, and the rest of the data follow.

First@rawDatRvr

rawDatRvr[[2;;5]]

Format the list of ranges and the locations from which they were taken. We want each row to be {{easting, northing}, range}.

hitsRvr=Transpose[{rawDatRvr[[All,3;;4]],rawDatRvr[[All,7]]}];

hitsRvr[[1;;5]]

Drop the labels in the first row.

hitsRvr=Drop[hitsRvr,1];

Find the plot range by finding the range of the hitlist and then adding a margin.

eMinRvr=Min[hitsRvr[[All,1,1]]]

eMaxRvr=Max[hitsRvr[[All,1,1]]]

nMinRvr=Min[hitsRvr[[All,1,2]]]

nMaxRvr=Max[hitsRvr[[All,1,2]]]

Add a margin to the min and max lats and lons to establish a plot region.

margin=500;
plotRangeRvr={{eMinRvr,eMaxRvr},{nMinRvr,nMaxRvr}}+{{-margin,margin},{-margin,margin}}

Plot the list of locations from which WG Tiny obtained ranges.

hitPlotRvr=ListPlot[hitsRvr[[All,1]],PlotRange->plotRangeRvr,GridLines->Automatic,AspectRatio->Automatic,Frame->True,ImageSize->Medium,Joined->True]

Find the location and depth which minimizes the MSE when compared to the recorded ranges. Note that only the InteriorPoint method can be used with constraints, and I’m setting the constraints to be the edges of the plot. If the best solution is outside the ranges of the plot, this method will fail to find it. Sometimes the MaxIterations will have to be increased for the best solution to be found before the algorithm gives up.

solRvr=FindMinimum[{locDepthErrorENU[hitsRvr,{east,north},depth],plotRangeRvr[[1,1]]<east<plotRangeRvr[[1,2]],plotRangeRvr[[2,1]]<north<plotRangeRvr[[2,2]],3000<depth<4500},{east,north,depth},Method->"InteriorPoint",AccuracyGoal->2,MaxIterations->1000]

Convert from UTM to LatLong.

actFebLocRvr=GeoPosition[GeoGridPosition[{east,north,-depth},"UTMZone10"]/.solRvr[[2]]]

Plot the target location with a contour plot of the error surface.

conPlotRvr=ContourPlot[locDepthErrorENU[hitsRvr,{east,north},solRvr[[2,3,2]]],{east,plotRangeRvr[[1,1]],plotRangeRvr[[1,2]]},{north,plotRangeRvr[[2,1]],plotRangeRvr[[2,2]]},Contours->{100,500,1000,5000,10000},AspectRatio->Automatic,ContourStyle->GrayLevel[0.8],ContourShading->None,ImageSize->Medium]

Plot3D[locDepthErrorENU[hitsRvr,{east,north},solRvr[[2,3,2]]],{east,plotRangeRvr[[1,1]],plotRangeRvr[[1,2]]},{north,plotRangeRvr[[2,1]],plotRangeRvr[[2,2]]},ImageSize->Medium]

Show[hitPlotRvr,conPlotRvr,Graphics[{Red,PointSize[Large],Point[{solRvr[[2,1,2]],solRvr[[2,2,2]]}]}]]

Plot the ranges as a function of ping number.

ListPlot[rawDatRvr[[All,7]]]

ListPlot[Labeled[#,#]&/@rawDatRvr[[All,7]]]

Convert the Rover drop point from LatLong to UTM and add it to the plot.

dropLocRvr=GeoGridPosition[GeoPosition[{FromDMS[{35, 8.5048}],FromDMS[{-123, -0.2023}]}],"UTMZone10"]

Show[hitPlotRvr,conPlotRvr,Graphics[{Red,PointSize[Large],Point[{solRvr[[2,1,2]],solRvr[[2,2,2]]}],Green,Point[dropLocRvr[[1]]]}]]

Import the SES ranging data.

rawDatSES=(* Import["/Users/mcgill/Documents/My\ Projects/Pelagic-Benthic\ Coupling/Pulse\ 75/lc-rangeutm-20220207-180113.csv","CSV"]; *)
Import["/Volumes/ProjectLibrary/900502.BenthicRover/Rover.Deployment/Pulse_75/Rover\ Geolocation/lc-rangeutm-20220207-180113.csv"];

The column labels are in the first row, and the rest of the data follow.

First@rawDatSES

rawDatSES[[2;;5]]

Format the list of ranges and the locations from which they were taken. We want each row to be {{easting, northing}, range}.

hitsSES=Transpose[{rawDatSES[[All,3;;4]],rawDatSES[[All,7]]}];

hitsSES[[1;;5]]

Drop the labels in the first row.

hitsSES=Drop[hitsSES,1];

Find the plot range by finding the range of the hitlist and then adding a margin.

eMinSES=Min[hitsSES[[All,1,1]]]

eMaxSES=Max[hitsSES[[All,1,1]]]

nMinSES=Min[hitsSES[[All,1,2]]]

nMaxSES=Max[hitsSES[[All,1,2]]]

Add a margin to the min and max lats and lons to establish a plot region.

margin=500;
plotRangeSES={{eMinSES,eMaxSES},{nMinSES,nMaxSES}}+{{-margin,margin},{-margin,margin}}

Plot the list of locations from which WG Tiny obtained ranges.

hitPlotSES=ListPlot[hitsSES[[All,1]],PlotRange->plotRangeSES,GridLines->Automatic,AspectRatio->Automatic,Frame->True,ImageSize->Medium,Joined->True]

Find the location and depth which minimizes the MSE when compared to the recorded ranges. Note that only the InteriorPoint method can be used with constraints, and I’m setting the constraints to be the edges of the plot. If the best solution is outside the ranges of the plot, this method will fail to find it. Sometimes the MaxIterations will have to be increased for the best solution to be found before the algorithm gives up.

solSES=FindMinimum[{locDepthErrorENU[hitsSES,{east,north},depth],plotRangeSES[[1,1]]<east<plotRangeSES[[1,2]],plotRangeSES[[2,1]]<north<plotRangeSES[[2,2]],3000<depth<4500},{east,north,depth},Method->"InteriorPoint",AccuracyGoal->2,MaxIterations->1000]

Convert from UTM to LatLong.

actFebLocSES=GeoPosition[GeoGridPosition[{east,north,-depth},"UTMZone10"]/.solSES[[2]]]

Plot the target location with a contour plot of the error surface.

conPlotSES=ContourPlot[locDepthErrorENU[hitsSES,{east,north},solSES[[2,3,2]]],{east,plotRangeSES[[1,1]],plotRangeSES[[1,2]]},{north,plotRangeSES[[2,1]],plotRangeSES[[2,2]]},Contours->{100,500,1000,5000,10000},AspectRatio->Automatic,ContourStyle->GrayLevel[0.8],ContourShading->None,ImageSize->Medium]

Show[hitPlotSES,conPlotSES,Graphics[{Red,PointSize[Large],Point[{solSES[[2,1,2]],solSES[[2,2,2]]}]}]]

Plot the ranges as a function of ping number.

ListPlot[Labeled[#,#]&/@rawDatSES[[All,7]]]

Convert the SES drop point from LatLong to UTM and add it to the plot.

dropLocSES=GeoGridPosition[GeoPosition[{FromDMS[{35, 8.6714}],FromDMS[{-123, -0.0902}]}],"UTMZone10"]

Show[hitPlotSES,conPlotSES,Graphics[{Red,PointSize[Large],Point[{solSES[[2,1,2]],solSES[[2,2,2]]}],Green,Point[dropLocSES[[1]]]}]]

Show the Rover and SES positions on the same plot.

Show[Graphics[{
Orange,PointSize[Large],Point[{solSES[[2,1,2]],solSES[[2,2,2]]}],
Blue,Point[dropLocSES[[1]]],
Red,PointSize[Large],Point[{solRvr[[2,1,2]],solRvr[[2,2,2]]}],
Green,Point[dropLocRvr[[1]]],
Black,
Text["SES Location",{solSES[[2,1,2]],solSES[[2,2,2]]}+{80,30}],
Text["SES Drop Point",dropLocSES[[1]]-{80,30}],
Text["Rover Location",{solRvr[[2,1,2]],solRvr[[2,2,2]]}+{80,30}],
Text["Rover Drop Point",dropLocRvr[[1]]+{80,-30}]},
Frame->True,GridLines->Automatic,PlotRangePadding->100]]

roverToSESDistFeb=EuclideanDistance[{solRvr[[2,1,2]],solRvr[[2,2,2]],solRvr[[2,3,2]]},{solSES[[2,1,2]],solSES[[2,2,2]],solSES[[2,3,2]]}]

Show[Graphics[{
Orange,PointSize[Large],Point[{solSES[[2,1,2]],solSES[[2,2,2]]}],
Blue,Point[dropLocSES[[1]]],
Red,PointSize[Large],Point[{solRvr[[2,1,2]],solRvr[[2,2,2]]}],
Green,Point[dropLocRvr[[1]]],
Black,
Text["SES Location\r600 mab",{solSES[[2,1,2]],solSES[[2,2,2]]}+{80,30}],
Text["SES Drop Point",dropLocSES[[1]]-{80,30}],
Text["Rover Location\ron bottom",{solRvr[[2,1,2]],solRvr[[2,2,2]]}+{80,30}],
Text["Rover Drop Point",dropLocRvr[[1]]+{80,-30}],
Arrow[{{solSES[[2,1,2]],solSES[[2,2,2]]},{solRvr[[2,1,2]],solRvr[[2,2,2]]}}],
Text["706 meters apart",{499870,3.8892 (10^6)}]},
Frame->True,GridLines->Automatic,PlotRangePadding->100]]

April Wave Glider Mission

Estimate Rover’s position on 25Apr22 by dead reckoning from the 4Feb22 location. Assume a speed of 4.4 m per day on a course of 71 deg true, which is the course and speed determined in 2019/2022 when we last had good geopositions for Rover.

actFebLocRvr

daysFeb2Apr=DateDifference[{2022,2,4},{2022,4,25}]//QuantityMagnitude

estAprLoc=GeoDestination[actFebLocRvr,{4.4*daysFeb2Apr,71}]

NumberForm[estAprLoc,{7,4}]

GeoListPlot[{actFebLocRvr,estAprLoc},Frame->True,Joined->True,GeoGridLines->Automatic,GeoProjection->"Equirectangular"]

Find the actual Rover location on 27Apr22 from Loop and Cross hits provided by Kent.

rawDatRvrApr=
Import["/Volumes/ProjectLibrary/900502.BenthicRover/Rover.Deployment/Pulse_75/Rover\ Geolocation/lc-rangeutm-20220427-152531.csv"];

The column labels are in the first row, and the rest of the data follow.

First@rawDatRvrApr

rawDatRvrApr[[2;;5]]

Format the list of ranges and the locations from which they were taken. We want each row to be {{easting, northing}, range}.

hitsRvrApr=Transpose[{rawDatRvrApr[[All,3;;4]],rawDatRvrApr[[All,7]]}];

hitsRvrApr[[1;;5]]

Drop the labels in the first row.

hitsRvrApr=Drop[hitsRvrApr,1];

Find the plot range by finding the range of the hitlist and then adding a margin.

eMinRvrApr=Min[hitsRvrApr[[All,1,1]]]

eMaxRvrApr=Max[hitsRvrApr[[All,1,1]]]

nMinRvrApr=Min[hitsRvrApr[[All,1,2]]]

nMaxRvrApr=Max[hitsRvrApr[[All,1,2]]]

Add a margin to the min and max lats and lons to establish a plot region.

margin=500;
plotRangeRvrApr={{eMinRvrApr,eMaxRvrApr},{nMinRvrApr,nMaxRvrApr}}+{{-margin,margin},{-margin,margin}}

Plot the list of locations from which WG Tiny obtained ranges.

hitPlotRvrApr=ListPlot[hitsRvrApr[[All,1]],PlotRange->plotRangeRvrApr,GridLines->Automatic,AspectRatio->Automatic,Frame->True,ImageSize->Medium,Joined->True]

Find the location and depth which minimizes the MSE when compared to the recorded ranges. Note that only the InteriorPoint method can be used with constraints, and I’m setting the constraints to be the edges of the plot. If the best solution is outside the ranges of the plot, this method will fail to find it. Sometimes the MaxIterations will have to be increased for the best solution to be found before the algorithm gives up.

solRvrApr=FindMinimum[{locDepthErrorENU[hitsRvrApr,{east,north},depth],plotRangeRvrApr[[1,1]]<east<plotRangeRvrApr[[1,2]],plotRangeRvrApr[[2,1]]<north<plotRangeRvrApr[[2,2]],3000<depth<4500},{east,north,depth},Method->"InteriorPoint",AccuracyGoal->2,MaxIterations->1000]

Convert from UTM to LatLong.

actAprLocRvr=GeoPosition[GeoGridPosition[{east,north,-depth},"UTMZone10"]/.solRvrApr[[2]]]

Plot the target location with a contour plot of the error surface.

conPlotRvrApr=ContourPlot[locDepthErrorENU[hitsRvrApr,{east,north},solRvrApr[[2,3,2]]],{east,plotRangeRvrApr[[1,1]],plotRangeRvrApr[[1,2]]},{north,plotRangeRvrApr[[2,1]],plotRangeRvrApr[[2,2]]},Contours->{100,500,1000,5000,10000},AspectRatio->Automatic,ContourStyle->GrayLevel[0.8],ContourShading->None,ImageSize->Medium]

Show[hitPlotRvrApr,conPlotRvrApr,Graphics[{Red,PointSize[Large],Point[{solRvrApr[[2,1,2]],solRvrApr[[2,2,2]]}]}]]

Find the distance and direction that Rover traveled between Feb and Apr.

dispFeb2Apr=GeoDisplacement[actFebLocRvr,actAprLocRvr]

July Wave Glider Mission

Estimate Rover’s current position on 25Jul22 based on travelling the same course and speed as she did between Feb and Apr. First find the number of days between the Apr and Jul geolocations.

daysApr2Jul=DateDifference[{2022,4,27},{2022,7,25}]//QuantityMagnitude

Find Rover’s average speed in meters/day between Feb and Apr. Note that the actual geolocation was 2 days after the position was estimated in Apr.

dispFeb2Apr[[1,1]]

speedFeb2Apr=((dispFeb2Apr[[1,1]])/(daysFeb2Apr+2))

Estimate the distance Rover traveled between Apr and Jul.

estDistApr2Jul=daysApr2Jul speedFeb2Apr

Estimate Rover’s Jul location assuming this distance and the same direction of travel from Feb to Apr.

dispFeb2Apr

estJulLocRvr=GeoDestination[actAprLocRvr,{estDistApr2Jul,dispFeb2Apr[[1,2]]}]

Plot Rover’s path since deployment.

GeoListPlot[{actFebLocRvr,actAprLocRvr,estJulLocRvr},Frame->True,Joined->True,GeoGridLines->Automatic,GeoProjection->"Equirectangular"]

Import the actual ranges and geolocate Rover.

rawDatRvrJul=Import["/Volumes/ProjectLibrary/900502.BenthicRover/Rover.Deployment/Pulse_75/Rover\ Geolocation/ranges_202207261708.log","CSV"];

The column labels are in the first row, and the rest of the data follow.

First@rawDatRvrJul

rawDatRvrJul[[2;;6]]

Format the list of ranges and the locations from which they were taken. We want each row to be {{easting, northing}, range}.

hitsRvrJul=Transpose[{Drop[rawDatRvrJul,1][[All,3;;4]],Drop[rawDatRvrJul,1][[All,5]]}]

Find the plot range by finding the range of the hitlist and then adding a margin.

eMinRvrJul=Min[hitsRvrJul[[All,1,1]]]

eMaxRvrJul=Max[hitsRvrJul[[All,1,1]]]

nMinRvrJul=Min[hitsRvrJul[[All,1,2]]]

nMaxRvrJul=Max[hitsRvrJul[[All,1,2]]]

Add a margin to the min and max lats and lons to establish a plot region.

margin=500;
plotRangeRvrJul={{eMinRvrJul,eMaxRvrJul},{nMinRvrJul,nMaxRvrJul}}+{{-margin,margin},{-margin,margin}}

Plot the list of locations from which WG Tiny obtained ranges.

hitPlotRvrJul=ListPlot[hitsRvrJul[[All,1]],PlotRange->plotRangeRvrJul,GridLines->Automatic,AspectRatio->Automatic,Frame->True,ImageSize->Medium,Joined->True]

Find the location and depth which minimizes the MSE when compared to the recorded ranges. Note that only the InteriorPoint method can be used with constraints, and I’m setting the constraints to be the edges of the plot. If the best solution is outside the ranges of the plot, this method will fail to find it. Sometimes the MaxIterations will have to be increased for the best solution to be found before the algorithm gives up.

solRvrJul=FindMinimum[{locDepthErrorENU[hitsRvrJul,{east,north},depth],plotRangeRvrJul[[1,1]]<east<plotRangeRvrJul[[1,2]],plotRangeRvrJul[[2,1]]<north<plotRangeRvrJul[[2,2]],3000<depth<4500},{east,north,depth},Method->"InteriorPoint",AccuracyGoal->2,MaxIterations->1000]

Convert from UTM to LatLong.

actJulLocRvr=GeoPosition[GeoGridPosition[{east,north,-depth},"UTMZone10"]/.solRvrJul[[2]]]

SetPrecision[actJulLocRvr,7]

Plot the target location with a contour plot of the error surface.

conPlotRvrJul=ContourPlot[locDepthErrorENU[hitsRvrJul,{east,north},solRvrJul[[2,3,2]]],{east,plotRangeRvrJul[[1,1]],plotRangeRvrJul[[1,2]]},{north,plotRangeRvrJul[[2,1]],plotRangeRvrJul[[2,2]]},Contours->{100,500,1000,5000,10000},AspectRatio->Automatic,ContourStyle->GrayLevel[0.8],ContourShading->None,ImageSize->Medium]

Plot3D[locDepthErrorENU[hitsRvrJul,{east,north},solRvrJul[[2,3,2]]],{east,plotRangeRvrJul[[1,1]],plotRangeRvrJul[[1,2]]},{north,plotRangeRvrJul[[2,1]],plotRangeRvrJul[[2,2]]},ImageSize->Medium]

Show[hitPlotRvrJul,conPlotRvrJul,Graphics[{Red,PointSize[Large],Point[{solRvrJul[[2,1,2]],solRvrJul[[2,2,2]]}]}]]

Find how far and on what heading Rover has traveled since Apr.

dispApr2Jul=GeoDisplacement[actAprLocRvr,actJulLocRvr]

Plot Rover’s path since deployment.

locPlotJul=GeoListPlot[{actFebLocRvr,actAprLocRvr,actJulLocRvr},Frame->True,Joined->True,GeoGridLines->Automatic,GeoProjection->"Equirectangular"]

Show[locPlotJul,Graphics[Text["February\nDeployment\nLocation\n\n\n\n",actFebLocRvr]],Graphics[Text["April\nLocation\n\n\n",actAprLocRvr]],Graphics[Text["\n\n\nJuly\nLocation",actJulLocRvr]]]

Find how much my geolocation of Rover in July differs from Brent Jones’ geolocation from the same list of ranges.

actJulLocRvrBrent=GeoPosition[{35.150119,-122.997447}]

GeoDisplacement[actJulLocRvr,actJulLocRvrBrent]