Developer Zone

Advanced Software Development with MATLAB

The Fast and the Fouriers!

UPDATE: We did it and it was a lot of fun! It looks like the tracking worked out as well so that was fun to see. One slight hiccup was that we ended up tracking more than 8000 points and ThingSpeak returns 8000 points per call. No biggie! We just needed to seperate out all our calls to ThingSpeak to get all the data. The data is all there on the ThingSpeak channel I just needed to update the visualization code. I've included the updated version below to show all the points. I also distinguished the drive from MathWorks HQ over to the start from the actual course I took.

Hi folks! Check it out! 11 MathWorkers and I are about to embark on a MathWorks adventure running the 200(ish) miles of Cape Cod. We start running at 2:30 PM Eastern Standard Time tomorrow (Friday May 12th). It should be an adventure, and we were excited to help with a great cause.

I thought it would be fun to use a little MATLAB mobile goodness to broadcast our progress in real time. Check it out and track us either through the ThingSpeak page or just on this page as the map below should be updated in real time.

Hopefully I don't have any bugs, since I will be busy running and supporting the other runners and it might be tough to fix any mistakes I've made in the code. Remember, it's live folks!

For reference, here is the code I will be running from my iPhone using the MATLAB Support Package for Apple iOS Sensors to send my GPS data. Note I will be doing this from an instance of MATLAB in the cloud. Awesome! Here's the function. It just takes the instance of mobiledev:

function trackTheFouriers(m)

disp("Tracking the Fouriers: " + string(datetime('now')))

m.PositionSensorEnabled = 1;
m.Logging = 1;
m.SampleRate = 1;

channel = 261391;
writeKey = 'XXXXXXXXXXXXXXXX'; % Not the real write key :-P
readKey = 'XXXXXXXXXXXXXXXX';% Not the real read key :-P

[Latitude, Longitude, posTS, Speed, ~, Altitude, Accuracy] = m.poslog;

% Only write to the channel when there are changes in latitude, longitude, or accuracy
Timestamps = datetime(m.InitialTimestamp) + seconds(posTS);

lastDataPoint = thingSpeakRead(channel, 'OutputFormat', 'table', 'NumPoints', 1, 'ReadKey', readKey,'Location',true);
changeTable = [...
    lastDataPoint(:,{'Latitude', 'Longitude', 'Accuracy'});
    table(Latitude, Longitude, Accuracy)
    ];

% Find changing data
hasChanged = @(value) abs(diff(value)) > 1e-5;

changeIdx = hasChanged(changeTable.Accuracy) | hasChanged(changeTable.Longitude) | hasChanged(changeTable.Latitude);
T = table(Timestamps(changeIdx), Accuracy(changeIdx), Speed(changeIdx),'VariableNames', {'Timestamps', 'Accuracy', 'Speed'});
h = height(T);
if  h > 0
    disp("Writing " + h + " data points")
    thingSpeakWrite(channel, T, 'WriteKey', writeKey,'Location', [Latitude(changeIdx), Longitude(changeIdx), Altitude(changeIdx)]);
else
    disp("No data to write");
end

m.discardlogs;

Also, here is the visualization code I used to plot our course continually during the race:

dawnOfTime = datetime(2000,1,1);
endTime = datetime('now');

% Grab the results. Keep asking for results until we have the full dataset.
T = table;
intermediateResults = thingSpeakRead(261391,'OutputFormat', 'table', ...
    'DateRange',[dawnOfTime, endTime] , 'ReadKey','XXXXXXXXXXXXXXXX','Location',true);
while ~isempty(intermediateResults)
    T = [intermediateResults; T]; %#ok<AGROW>
    endTime = T.Timestamps(1) - sqrt(eps); % Adjust our window to get more data
    intermediateResults = thingSpeakRead(261391,'OutputFormat', 'table', ...
        'DateRange',[dawnOfTime, endTime] , 'ReadKey','XXXXXXXXXXXXXXXX','Location',true);
end

% Generate the map
serverURL = 'http://raster.nationalmap.gov/arcgis/services/Orthoimagery/USGS_EROS_Ortho_1Foot/ImageServer/WMSServer?';
info = wmsinfo(serverURL);

latlim = [41.4,42.4];
lonlim = [-71.4 -69.9];
height = round(diff(latlim)*1000);
width = round(diff(lonlim)*1000);
[A, R] = wmsread(info.Layer, 'Latlim', latlim, 'Lonlim', lonlim,...
    'ImageHeight', height,'ImageWidth',width);
% Show the map
fig = figure;
fig.Position(3:4) = [width height];
ax = axes('Parent',fig);
geoshow(ax, A,R)
hold on
axis tight

% Show the start & end points
geoshow(ax,42.271, -70.857,'DisplayType', 'point', 'MarkerSize',20,'LineWidth',4,'Marker', 'v');
geoshow(ax, 42.053, -70.189,'DisplayType', 'point', 'MarkerSize',20,'LineWidth',4,'Marker', 'h');


%T.Timestamps = T.Timestamps + hours(4); % adjust recorded timezone offset
drivingOver = T.Timestamps < datetime(2017,5,12,14,30,0);
driveData = T(drivingOver,:);
drivePath = geoshow(ax, driveData.Latitude, driveData.Longitude,'DisplayType', 'line', 'LineWidth',3,'LineStyle',':','Color','red');

raceData = T(~drivingOver,:);
geoshow(ax,  raceData.Latitude(end), raceData.Longitude(end),'DisplayType', 'point', 'MarkerSize',20,'LineWidth',4,'Marker', 'o');
racePath = geoshow(ax, raceData.Latitude, raceData.Longitude,'DisplayType', 'line', 'LineWidth',3);

legend([drivePath, racePath], {'Drive from TMW', 'Race Path'})

Cheer us on! I'll try to check back in from time to time during the race to see how things are working.




Published with MATLAB® R2017a

|
  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.