function ssobj = ss(obj,varargin)
% ssobj = ss(essobj)
% ssobj = ss(essobj, method)
%
% Convert ess object to pure ss object.
%
% The method argument can be one of the following:
%
% - 'measured' (default): The noise input is discarded. This is
% equivalent to SS(A,B,C,D)
%
% - 'augmented': Noise input is appended to deterministic input. This
% is equivalent to SS(A,[B,L,0],C,[D,0,1]), where the 1 is a unit
% gain input for measurement noise, while the 0's are appropriate
% paddings.
%
% Note that NO scaling is applied to L. Noise series which are
% used as inputs therefore need to have correct (possibly non-unit)
% variances! This is in contrast to idParametric/ss which scales
% input matrices with sqrt(NoiseVariance).
%
% - 'noise': Only the noise input is kept, while the deterministic
% input is droped. This is equivalent to SS(A,[L,0],[0,1]) (see
% above).
%
% See also IDPARAMETRIC/SS
% TODO
% * Should the scaling be changed?
% - non-zero correlations must be preserved!!
% * Display method has to be changed if ess ever gets a 'NoiseName' field!!
METHOD = 'measured';
for ii = 1:(nargin - 1)
switch varargin{ii}
case 'noise', METHOD = 'noise';
case 'augmented', METHOD = 'augmented';
otherwise warning('unknown method');
end
end
% read ss properties into struct
% this automatically implements 'measured'
props = struct();
names = properties(ss);
for ii=1:length(names)
props.(names{ii})=obj.(names{ii});
end
% system dimensions
% sn = dimension state
% on = dimension measurement
% dn = dimension deterministic input
% pn = dimension process noise
[on sn] = size(obj.c);
dn = size(obj.b,2);
pn = size(obj.l,2);
% create cell with noise names
% note: this has to be changed if ess ever gets a 'NoiseName' field!!
wlabels = arrayfun(@(x) sprintf('w%d',x),1:size(obj.l,2),'UniformOutput',false);
vlabels = arrayfun(@(x) sprintf('v%d',x),1:on,'UniformOutput',false);
% set properties in temporary struct
% append noise input as deterministic input
%
% this has to be done in this way to circumvent the dimensionality
% checks of ss objects
switch METHOD
case 'augmented'
% append process noise input to deterministic input
props.b = [props.b,obj.l,zeros(sn,on)];
% append unit gain measurement noise input AFTER process noise input
props.d = [props.d,zeros(on,size(obj.l,2)),eye(on)];
% pad InputName such that length fits new input length
props.InputName = {props.InputName{:},wlabels{:},vlabels{:}};
case 'noise'
% replace deterministic input with noise input
props.b = [obj.l,zeros(sn,on)];
props.d = [zeros(on,size(obj.l,2)),eye(on)];
% pad InputName such that length fits new input length
props.InputName = {wlabels{:},vlabels{:}};
otherwise % do nothing
end
% write properties back into new ss object
ssobj = ss();
for ii = 1:length(names)
ssobj.(names{ii}) = props.(names{ii});
end
% set input group names
% (this overwrites existing values)
switch METHOD
case 'measured'
ssobj.InputGroup.KnownInput = 1:dn;
case 'augmented'
ssobj.InputGroup.KnownInput = 1:dn;
ssobj.InputGroup.ProcessNoise = dn+1:dn+pn;
ssobj.InputGroup.MeasurementNoise = dn+pn+1:dn+pn+on;
case 'noise'
ssobj.InputGroup.ProcessNoise = 1:pn;
ssobj.InputGroup.MeasurementNoise = pn+1:pn+on;
end