0

I am trying to return a variable number of outputs, but sometimes these outputs have to be passed through an intermediary function, and sometimes not. A similar question was asked here but never answered because no specific example was given.

I am using the MATLAB built-in Sensor Data Collection functions and constantly logging accelerometer data and GPS data on a phone (there are actually 7 sensor types, but I simplified it to 2 types for this question). This data is retrieved with unique functions. Accelerometer data (3 output arrays) is output from the "accellog" built-in function, and GPS data (7 output arrays) is output from the "poslog" built-in function, where n is the number of measurements.

I have two functions that I use to pull data from these datasets:

Function 1: "GetData" pulls all the data from a specified dataset. A string "sensorDataString" specifies the type of data that is being requested (this is needed so that functions can be generalized for different sensors).

function varargout = GetData(mobileObj, sensorDataString)
    switch sensorDataString
        case 'Acceleration'
            [varargout{1:2}] = accellog(mobileObj);
        case 'GPS'
            [varargout{1:7}] = poslog(mobileObj);
    end
end

Function 2: "GetSecondsOfData" returns a portion of the data set based on waiting a specified amount of time between , but relies on the "GetData" function to grab data in the first place.

% Return a set of mobile sensor measurements that span the specified number of seconds
function varargout = GetSecondsOfData(mobileObj, sensorDataString, numSeconds)
    [tempdata, ~] = GetData(mobileObj, sensorDataString);
    startIndx = size(tempdata,1) + 1; % Determine the starting index of measurements

    pause(numSeconds) % Collect data for the specified number of seconds
    varargout = GetData(mobileObj, sensorDataString);
    for i = 1:size(varargout)
        varargout{i} = varargout{i}(startIndx:end,:); % Pull out desired section of data
    end
end

The errors occur when attempting to assign varargout from "GetData" and "GetSecondsOfData".

Is there a generalized way to pass a variable number of outputs from one function then pass these outputs through the calling function? (Or is there a better approach to this problem?)

I can use a switch-case structure to determine the number of outputs in the "GetSecondsofData" function, but this looks messy with 7 sensors. I could also output data in a different form (cell arrays), but outputting multiple variable with varargout is the simplest for handling especially since I will sometimes use "GetData" and sometimes use "GetSecondsOfData", so I would have to assign outputs from cells.

If you know the number of outputs you can use code like:

[varargout{1:7}] = poslog(mobileObj);

I'm looking for something that looks more like this, where the number of cells does not have to be specified:

varargout = GetData(mobileObj, sensorDataString);
blobberman
  • 11
  • 2

1 Answers1

0

Ok this is a full rewrite as it seem I did not understand your actual problem the last time.

The varargout variable, when it is still in the called function, is just a cell array. It only get dispatched in several outputs when the function returns. If handling a variable number of output argument causes you a problem, you could just use the same way of constructing the output (a cell array), but just don't use varargout, keep the cell array as it is so you have a fixed number of output (with a variable number of element indeed, but that doesn't affect how you call the function, only how you parse it once you received the data).

If you want you can add some optional output info to help the parsing later on.

Consider:

function [SensorData, SensorDataInfo] = GetData(mobileObj, sensorDataString)
    switch sensorDataString
        
        case 'Acceleration'
            nSensors = 2 ;
            % Simulate your 2 sensors output: [varargout{1:2}] = accellog(mobileObj);
            for k=1:nSensors
                SensorData{k} = randi(10,10,1) ;
            end
            
        case 'GPS'
            nSensors = 7 ;
            % Simulate your 7 sensors output: [varargout{1:2}] = poslog(mobileObj);
            for k=1:nSensors
                SensorData{k} = randi(10,10,1) ;
            end
    end
    
    if nargout > 1
        SensorDataInfo.nSensor    = 7 ;
        SensorDataInfo.SensorType = sensorDataString ;
    end
end

Now you can always call the function in the same way. For GPS data:

>> [SensData , SensInfo] = GetData([], 'GPS')
SensData = 
    [10x1 double]    [10x1 double]    [10x1 double]    [10x1 double]    [10x1 double]    [10x1 double]    [10x1 double]
SensInfo = 
       nSensor: 7
    SensorType: 'GPS'

or for accelerometer data:

>> [SensData , SensInfo] = GetData([], 'Acceleration')
SensData = 
    [10x1 double]    [10x1 double]
SensInfo = 
       nSensor: 2
    SensorType: 'Acceleration'
Hoki
  • 11,637
  • 1
  • 24
  • 43
  • Setting varargout by using the number of outputs is the problem itself. If you output nSensors and varargout simultaneously, you would not be able to use the nSensors data to specify the size of varargout being assigned. Right? – blobberman Oct 15 '20 at 16:38
  • Yes sorry I did not understood your problem correctly the first time. I rewrote the answer proposing another way to approach it. – Hoki Oct 16 '20 at 09:39