How to plot real time data from text file in MATLAB

7.3k views Asked by At

Im new to matlab coding so im still trying to get my head around things. Pretty much im working with interia sensors which output the sensors orientation data every 10ms. Im able to store this data into a text file which is continuously updating.

My task now is to plot this data in real time. This involves continuously accessing and reading from the text file (every 10ms if possible) and graph this data with respect to time. Can any of you guys give me some guidance onto what would be the most effective way to do this.

At this moment in time, the text file only stores data about one parameter (the x coordinate of the sensor). I can store this data in 2 way: Method 1: New data every 10ms. Each is stored in a new line. Method 2: I can make the text file only have the most recent piece of data (erasing previous data) Im able to use either of these methods.. whatever you guys think would be easier.

Ive tried using other 3rd party software to graph this data from the text file, but they all seemed really jumpy and couldnt read from the text file fast enough.

Thanks.

2

There are 2 answers

6
ljk07 On BEST ANSWER

A MATLAB timer object will help. See, for example, this link Using MATLAB to process files in real-time after every instance a file is created by a separate program.

There may be some worry regarding the simultaneous write (your other process) and read (MATLAB) to a single file. Your situation may be more suited to a pipe rather than a file: Pipe vs. Temporary File but I will proceed with a MATLAB based solution for timed file reads and plot updates.

I emulated your situation and learned a few things:

  • The MATLAB file handle stores the current position. However if the end of file flag is set for a file-id MATLAB will not look for new data when a subsequent call to fread is made. See the work arounds using fseek in the readFile function below.
  • 10 ms is optimistic. MATLAB doesn't miss points but each update typically adds four or more data points rather than just one.
  • If the source of the data is using buffered file writes MATLAB won't see new data until the buffer is flushed to disk. The python code below was used to emulate the source of your data. The file was opened to write without buffering: fobj = open('test.dat', 'wb', 0).

MATLAB code below:

function [t] = livePlot(period, filename)
    //%   inputs : period : update rate in seconds
    //%            filename : name of the file to get data from
    //%
    //%   outputs: t      : the timer object
    //%                     >> stop(t) 
    //%                     ends streaming
    //%%

    close all;        
    t = timer('StartDelay', 1, 'Period', period, ...
              'ExecutionMode', 'fixedRate');
    //%% timer object callback functions
    t.StopFcn  = {@stopFigure};
    t.TimerFcn = {@updateFigure};
    //%% initialize timer object user data
    d = get(t, 'UserData');
    d.data = []; % array for the data to plot
    axes('Position', [0 0 1 1], 'Visible', 'off');
    d.axes_handle = axes('Position', [.2 .1 .7 .8]);
    d.line_handle = plot(NaN,NaN);
    d.fid = fopen(filename, 'r');    
    set(t, 'UserData', d);    
    start(t);
end

function stopFigure(obj, event)
    //% close function handle
    d = get(obj, 'UserData');
    fclose(d.fid);
end

function updateFigure(obj, event)
    d = get(obj, 'UserData');        
    //% read new data from file
    tmp = readFile(obj);
    //% append to array in user data
    d.data = [d.data transpose(tmp)];
    //% update the plot 
    set(gcf, 'CurrentAxes', d.axes_handle);
    set(d.line_handle, 'XData', 1:length(d.data), 'YData', d.data);
    //% store the timer object user-data
    set(obj, 'UserData', d);
end

function [tmp] = readFile(obj)
    //% read binary data. file-ID is in the timer user-data
    d = get(obj, 'UserData');
    tmp = fread(d.fid);
    fprintf('Current file location : %d \n', ftell(d.fid));
    //% fprintf('End of file indicator : %d \n', feof(d.fid));
    //% reset the end-of-file indicator
    fseek(d.fid, -1, 0);
    fseek(d.fid, 1, 0);
    //% fprintf('End of file indicator : %d \n', feof(d.fid));
    set(obj, 'UserData', d); 
end

Python code to write data to a file every ~ 10 milliseconds:

#!/anaconda/bin/python
import numpy as np
from time import sleep
sleep_time = 0.01
sigma = 5
fobj = open('test.dat', 'wb', 0)
for i in range(5000):
    sleep(sleep_time)
    x = int(np.random.normal(sigma))
    fobj.write('%c' % x)
fobj.close()
0
Daniel On

You can't plot using hard real time conditions, thus it can always happen that matlab misses a 10ms timeslot. You have to use option 2 to get all data.

To get started: Write a function which only reads the new data which was written since last call. To achieve this, do not close the file handle. It stores the position.