Code covered by the MathWorks Limited License

Highlights from
Android Sensor support from MATLAB (R2013a, R2013b)

image thumbnail

Android Sensor support from MATLAB (R2013a, R2013b)

by

 

31 Jul 2013 (Updated )

Use MATLAB to acquire sensor data from built-in sensors on your Android device.

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

matlab.mobilesensor.internal.mobileSensorExplorer.SensorVisualization
%   Copyright 2013 The MathWorks, Inc.

classdef SensorVisualization < handle
    
    methods
        function obj = SensorVisualization(sensorName, varargin)

            obj.isAxisCreated = false;
            obj.isSensorGroupCreated = false;
            
            % validate input: Must be at least 1 parameter
            if nargin == 0
                error('MATLAB:sensorvisualization:noparams','sensorName is required')
            end
            
            % validate input: sensorName must be a known name
            if nargin >= 1 && ~any(strcmp(sensorName,{'Acceleration','AngularVelocity',...
                                        'MagneticField',...
                                        'LatitudeLongitude', 'Altitude',...
                                        'Speed','Course','Orientation'}))
                error('MATLAB:sensorvisualization:invalidSensor','sensorName must be one of the supported sensors.')
            end
            obj.sensorName = sensorName;
            
            % validate input: if a sensorgroup or device type is specified,
            % it must be a valid sensorgroup object 'AppleMobile' or 'AndroidMobile'
            if nargin >= 2
                deviceTypeOrSG = varargin{1};
                if ischar(deviceTypeOrSG)
                    if ~any(strcmp(deviceTypeOrSG,{'AppleMobile','AndroidMobile'}))
                        error('MATLAB:sensorvisualization:invalidDeviceType','deviceTypeOrSG must be sensorgroup or ''AppleMobile'' or ''AndroidMobile''')
                    end
                    obj.sg = sensorgroup.empty;
                elseif isa(deviceTypeOrSG,'sensorgroup')
                    obj.sg = deviceTypeOrSG;
                else
                    error('MATLAB:sensorvisualization:invalidSensorGroup','deviceTypeOrSG must be sensorgroup or ''AppleMobile'' or ''AndroidMobile''')
                end
            else    
                obj.sg = sensorgroup.empty;
            end
            
            % validate input: if an axes is specified, it must be valid axis
            if nargin >= 3
                obj.a = varargin{2};
                if ~ishghandle(obj.a) || ~strcmp(get(obj.a,'Type'),'axes')
                    error('MATLAB:sensorvisualization:invalidAxes','a must be an axes')
                end
            else
                obj.a = [];
            end
            
            % If we've validated the inputs, and there's no sensorgroup
            % yet, then create it.
            if isempty(obj.sg)
                obj.isSensorGroupCreated = true;
                obj.sg = sensorgroup(deviceTypeOrSG);
            end
            
            % If we've validated the inputs, and there's no axes yet, then
            % create it.
            if isempty(obj.a)
                obj.isAxisCreated = true;
                obj.a = gca;
            end
            
            % Create an update timer
            obj.updateTimer = timer(  'BusyMode','drop',...
                    'ExecutionMode','fixedRate',...
                    'Period',.1,...
                    'StartDelay',0,...
                    'ErrorFcn',@(src,event)handleError(obj,src,event),...
                    'TimerFcn',@(src,event)handleUpdate(obj,src,event));
            start(obj.updateTimer)
        end

        function delete(obj)
            try
                stop(obj.updateTimer);
            catch %#ok<CTCH>
            end
            if obj.isSensorGroupCreated
                try
                    delete(obj.sg);
                catch %#ok<CTCH>
                end
            end
            if obj.isAxisCreated
                try
                    close(get(obj.a,'Parent'))
                catch %#ok<CTCH>
                end
            end
            try
                delete(obj.updateTimer);
            catch %#ok<CTCH>
            end
        end
        
    end

    properties(GetAccess = protected,SetAccess = private)
        sensorName
        sg
        a
        currentXLim
    end

    methods (Access=protected)
        function processDataImpl(obj, data, ts)     
            if isempty(obj.hLines)
                plotParam = cell(1,size(data,2) * 2);
                for iColumn = 1:size(data,2)
                    plotParam{iColumn * 2 - 1} = ts;
                    plotParam{iColumn * 2} = data(:,iColumn);
                end
                obj.hLines = plot(obj.a,plotParam{:});
                title(obj.a,obj.sensorName)
                info = obj.getSensorInfo();
                ylabel(obj.a,info.unitName);

                if ~matlab.graphics.internal.isGraphicsVersion1()
                    legend(obj.a,info.legendText);
                end
                
                %datetick(obj.a,'x');
                ylim(obj.a,info.YLimit);
                obj.currentXLim = get(obj.a,'XLim');
            else
                for iColumn = 1:size(data,2)
                    set(obj.hLines(iColumn),'XData',ts,'YData',data(:,iColumn));
                end
                
                if ts(end, :) >= obj.currentXLim(2)
                    %datetick(obj.a,'x');
                    obj.currentXLim = get(obj.a,'XLim');
                end
            end
        end

        function handleError(~,~,~)   
            % Ignore errors
        end

        function handleUpdate(obj,~,~)   
            try
                switch obj.sensorName
                    case 'Acceleration'
                        [data, ts] = obj.sg.accellog();
                    case 'AngularVelocity'
                        [data, ts] = obj.sg.angvellog();
                    case 'MagneticField'
                        [data, ts] = obj.sg.magfieldlog();
                    case 'Orientation'
                        [data, ts] = obj.sg.orientlog();
                    case 'LatitudeLongitude'
                        [lat, long] = obj.sg.poslog();
                        data = [ lat, long];
                        ts = [];
                    case 'Altitude'
                        [~, ~, ~, data, ~, ts] = obj.sg.poslog();
                    case 'Speed'
                        [~, ~, data, ~, ~, ts] = obj.sg.poslog();
                    case 'Course'
                        [~, ~, ~, ~, data, ts] = obj.sg.poslog();
                end
                
                if isempty(data)
                    return
                end
                if size(data,1) < 3
                    return
                end

                try
                    obj.processDataImpl(data,ts);
                catch e
                    % If the axes is deleted, then the object should delete
                    % itself automatically.
                    if strcmp(e.identifier,'MATLAB:class:InvalidHandle')
                        delete(obj)
                        return
                    end
                end
            catch
            end
        end
    end

    properties(GetAccess = private,SetAccess = private)
        updateTimer
        hLines
        isAxisCreated
        isSensorGroupCreated
    end
        
    methods (Access=private)
        function info = getSensorInfo(obj)
            switch obj.sensorName
                case 'Acceleration'
                    info.unitName = 'm/s^2';
                    info.YLimit = 'auto';
                    info.legendText = {'x','y','z'};
                case 'MagneticAzimuth'
                    info.unitName = 'degree';
                    info.YLimit = [0 360];
                    info.legendText = {'Magnetic'};
                case 'Speed'
                    info.unitName = 'm/s';
                    info.YLimit = 'auto';
                    info.legendText = {'Speed'};
                case 'Course'
                    info.unitName = 'degree';
                    info.YLimit = [0 360];
                    info.legendText = {'Magnetic'};
                case 'AngularVelocity'
                    info.unitName = 'rad/sec';
                    info.YLimit = 'auto';
                    info.legendText = {'x','y','z'};
                case 'Altitude'
                    info.unitName = 'm above sea level';
                    info.YLimit = 'auto';
                    info.legendText = {'Altitude'};
                case 'GeodeticPosition'
                    info.unitName = 'degree';
                    info.YLimit = 'auto';
                    info.legendText = {'Latitude','Longitude'};
                case 'Latitude'
                    info.unitName = 'degree';
                    info.YLimit = 'auto';
                    info.legendText = {'Latitude'};
                case 'Longitude'
                    info.unitName = 'degree';
                    info.YLimit = 'auto';
                    info.legendText = {'Longitude'};
                case 'MagneticField'
                    info.unitName = 'Tesla';
                    info.YLimit = 'auto';
                    info.legendText = {'x','y','z'};
                case 'Orientation'
                    info.unitName = 'degree';
                    info.YLimit = [0 360];
                    info.legendText = {'Azimuth','Roll','Pitch'};
                case 'Roll'
                    info.unitName = 'deg';
                    info.YLimit = [0 360];
                    info.legendText = {''};
                case 'Pitch'
                    info.unitName = 'deg';
                    info.YLimit = [0 360];
                    info.legendText = {''};
                case 'Yaw'
                    info.unitName = 'deg';
                    info.YLimit = [0 360];
                    info.legendText = {''};
                otherwise
                    info.unitName = 'Unknown';
                    info.YLimit = 'auto';
                    info.legendText = {''};
            end
        end
    end
end

Contact us