diff --git a/+misc/+ss/connect.m b/+misc/+ss/connect.m new file mode 100644 index 0000000000000000000000000000000000000000..1305a3d5a085f7427496d0bfe4e6d584405f99d3 --- /dev/null +++ b/+misc/+ss/connect.m @@ -0,0 +1,31 @@ +function resultSs = connect(InputName, OutputName, options, varargin) +% connect Block-diagram interconnections of dynamic systems based on ss/connect. +% Different from the built-in function, InputName and OutputName are asserted to be +% unique. And it is more robust, since feedthroughs are removed before calling +% connect and are added afterwards again. + +% remove empty elements of varargin +if isa(options, 'ltioptions.connect') + inputSs = varargin(cellfun(@(v) ~isempty(v), varargin)); +else + if isa(options, 'numlti') + inputSs = [{options}, varargin(cellfun(@(v) ~isempty(v), varargin))]; + elseif ~isempty(options) + error("third input must be a connectOptions() or a StateSpaceModel"); + end + options = connectOptions('Simplify', false); +end + +% remove feedthrouhgs +for it = 1 : numel(inputSs) + inputSs{it} = misc.ss.removeInputOfOutput(ss(inputSs{it})); +end + +% call built-in function +resultSs = connect(inputSs{:}, ... + unique(InputName, 'stable'), ... + unique(OutputName, 'stable'), ... + options); + +end + diff --git a/+misc/+ss/errorSignal.m b/+misc/+ss/errorSignal.m new file mode 100644 index 0000000000000000000000000000000000000000..2d0245920a9f3de4a3243e5901d33bb829c918b5 --- /dev/null +++ b/+misc/+ss/errorSignal.m @@ -0,0 +1,41 @@ +function simError = errorSignal(simOriginal, simReference) +% MISC.SS.ERRORSIGNAL calculates the difference between all fields of simOriginal and +% simReference, and can be used to calculate the error signals of, for instance, an +% observer simulation, i.e. e = misc.ss.errorSignal(simPlant, simObserver); +% The resulting struct simError contains all fields that are fields of both +% simOriginal and simReference with the value +% simError.(fieldName) = simOriginal.(fieldName) - simReference(fieldName); +% +% Inputs: +% simOriginal struct of simulation data, for instance, output, state, input... +% simReference struct of simulation data, for instance, output, state, input... +% Outputs: +% simReference struct of difference of simOriginal and simReference fields +% +% Example: +% ------------------------------------------------------------------------- +% simOriginal.x = [2; 2]; +% simOriginal.u = 1; +% simReference.x = [1; 1]; +% simError = misc.ss.errorSignal(simOriginal, simReference); +% ------------------------------------------------------------------------- + +simError = struct(); +simOriginalFieldNames = fieldnames(simOriginal); +%simReferenceFieldNames = fieldnames(simOriginal); +for it = 1 : numel(simOriginalFieldNames) + if isfield(simReference, simOriginalFieldNames{it}) + if isstruct(simOriginal.(simOriginalFieldNames{it})) + simError.(simOriginalFieldNames{it}) ... + = misc.ss.errorSignal(... + simOriginal.(simOriginalFieldNames{it}), ... + simReference.(simOriginalFieldNames{it})); + else + simError.(simOriginalFieldNames{it}) ... + = simOriginal.(simOriginalFieldNames{it}) ... + - simReference.(simOriginalFieldNames{it}); + end + end +end % for it = 1 :... +end % misc.ss.errorSignal() + diff --git a/+misc/+ss/simulatePostproduction.m b/+misc/+ss/simulatePostproduction.m new file mode 100644 index 0000000000000000000000000000000000000000..7bec54d7b6ee39b13ba85a4bcf495cbfdd020c96 --- /dev/null +++ b/+misc/+ss/simulatePostproduction.m @@ -0,0 +1,17 @@ +function simData = simulatePostproduction(simData, varargin) +% MISC.SS.SIMULATEPOSTPRODUCTION goes through varargin and calls the method +% simulatePostproduction() of all that objects for which such a method is defined. +% +% Inputs: +% simData simulation data object +% varargin various objects, such as a plants model or a observer +% Outputs: +% simData simulation data object + +for it = 1 : numel(varargin) + if ismethod(varargin{it}, 'simulatePostproduction') + simData = varargin{it}.simulatePostproduction(simData); + end +end +end + diff --git a/+misc/backsteppingTransformation.m b/+misc/backsteppingTransformation.m index f843598d7ff825aace480c60b34dafabb1fc95c9..ee8c51bacbd92b295bc59f0a932cf118b97595b8 100644 --- a/+misc/backsteppingTransformation.m +++ b/+misc/backsteppingTransformation.m @@ -23,13 +23,19 @@ function xOut = backsteppingTransformation(xIn, backsteppingKernel, signOfIntegr columns = size(xIn, 3); % can not be obtained from xSize if ndims(xSize) == 2 z.grid = linspace(0, 1, z.n); z.gridKernel = linspace(0, 1, size(backsteppingKernel, 1)); - backsteppingKernel_noNan = zeros(size(backsteppingKernel)); - for it = 1:n - for jt = 1:n - backsteppingKernel_noNan(:, :, it, jt) = inpaint_nans(... - backsteppingKernel(:, :, it, jt)); - end + if any(isnan(backsteppingKernel)) + error('nan in kernel') end +% backsteppingKernel_noNan = zeros(size(backsteppingKernel)); +% for it = 1:n +% for jt = 1:n +% backsteppingKernel_noNan(:, :, it, jt) = inpaint_nans(... +% backsteppingKernel(:, :, it, jt)); +% end +% end +% else + backsteppingKernel_noNan = backsteppingKernel; + %end kernelInterpolant = numeric.interpolant(... {z.gridKernel, z.gridKernel, 1:n, 1:n}, ... backsteppingKernel_noNan, 'spline'); diff --git a/+unittests/+misc/testSs.m b/+unittests/+misc/testSs.m index 0623de805dc4c52aabaa172880e8bd6e12bbe763..cedad71387e27b25a97babd3bdabbfcf9f03d00b 100644 --- a/+unittests/+misc/testSs.m +++ b/+unittests/+misc/testSs.m @@ -3,6 +3,16 @@ function [tests] = testSs() % Detailed explanation goes here tests = functiontests(localfunctions()); end + +function testErrorSignal(tc) +simOriginal.x = [2; 2]; +simOriginal.u = 1; +simReference.x = [1; 1]; +simError = misc.ss.errorSignal(simOriginal, simReference); +tc.verifyEqual(simError.x, [1; 1]); +tc.verifyEqual(fieldnames(simError), {'x'}); +end + function testAdd2SignalName(tc) mySys = misc.ss.add2signalName(ss(1, 1, [1; 1], [], 'OutputName', {'a', 'b'}, ... 'InputName', {'c'}), ...