Skip to content

Commit

Permalink
object constructor must be in '@' directory and no more in parent dir…
Browse files Browse the repository at this point in the history
…ectory (compatibility)
  • Loading branch information
Nelson-numerical-software committed Nov 16, 2023
1 parent be780c8 commit 855c7f7
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 391 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- [#997](http://github.com/Nelson-numerical-software/nelson/issues/997) Macos BigSur Github CI support removed.
- `patch` and `fill` manages `FaceAlpha`.
- visibility title and labels.
- object constructor must be in '@' directory and no more in parent directory (compatibility).

## 0.7.10 (2023-10-27)

Expand Down
177 changes: 175 additions & 2 deletions modules/control_system/functions/@ss/ss.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%=============================================================================
% Copyright (c) 2017 September Daniel Mårtensson (Swedish Embedded Control Systems Toolbox)
% Copyright (c) 2023-present Allan CORNET (Nelson)
%=============================================================================
% This file is part of the Nelson.
Expand All @@ -7,7 +8,179 @@
% SPDX-License-Identifier: LGPL-3.0-or-later
% LICENCE_BLOCK_END
%=============================================================================
function sysOut = ss(sysIn)
sysOut = sysIn;
function varargout = ss(varargin)
% Generates a state space model from matrix A, B, C, D
% Input: A, B, C, D, Ts
% sys = ss(A, B, C, D)
% sys = ss(A, B, C, D, Ts)
% sys = ss(D)

nargoutchk(0, 1);

sys = [];
if (nargin == 0)
sys = ss_no_rhs();
end
if (nargin == 1)
sys = ss_one_rhs(varargin{1});
end
if (nargin == 4 || nargin == 5)
Ts = 0;
if (nargin == 5)
Ts = varargin{5};
isValidTs = isempty(Ts) || (isscalar(Ts) && (Ts == -1 || Ts >= 0));
if ~isValidTs
error(_('Ts property should be either a positive scalar, 0, or -1 to indicate that it is unspecified.'));
end
end
A = varargin{1};
B = varargin{2};
C = varargin{3};
D = varargin{4};
sys = ss_ABCD(A, B, C, D, Ts);
end
if (~isa(sys, 'ss'))
error(_('Wrong number of input arguments.'));
end
varargout{1} = sys;
end
%=============================================================================
function sys = ss_no_rhs()
ss = {};
ss.A = [];
ss.B = [];
ss.C = [];
ss.D = [];
ss.E = [];
ss.Scaled = false;
ss.Ts = 0;
ss.Internal = [];
ss.Internal.Version = 1;
ss.Internal.Ts = 0;
ss.TimeUnit = 'seconds';
ss.UserData = [];
sys = class(ss, 'ss');
end
%=============================================================================
function sys = ss_one_rhs(D)
if islti(D)
if isa(D, 'ss')
sys = D;
elseif isa(D, 'tf')
error(_('Supported LTI model expected.'))
else
error(_('Supported LTI model expected.'))
end
return
end
sys = ss_no_rhs();
sys.B = zeros(0, size(D, 2));
sys.C = zeros(size(D, 1),0);
sys.D = D;
sys.Internal.Ts = -2;
end
%=============================================================================
function sys = ss_ABCD(A, B, C, D, Ts)
[A, B, C, D, Ts] = adapt_ABCD(A, B, C, D, Ts);
msg = checkABCDE(A, B, C, D);

if ~isempty(msg)
error(msg.identifier, msg.message);
end

sys = ss_no_rhs();

sys.A = A;
sys.B = B;
sys.C = C;
sys.D = D;

if isequal(Ts, -1)
sys.Ts = 0;
sys.Internal.Ts = -1;
elseif isequal(Ts, -2)
sys.Ts = 0;
sys.Internal.Ts = -2;
else
sys.Ts = Ts;
sys.Internal.Ts = Ts;
end
end
%=============================================================================
function [A, B, C, D, Ts] = adapt_ABCD(A, B, C, D, Ts)
isDZero = (isscalar(D) && D(1) == 0);
if isempty(A) && isempty(B) && isempty(C)
[m, n] = size(D);
A = [];
B = zeros(0, n);
C = zeros(m, 0);
Ts = -2;
return;
end
new_row_for_C_or_D = max(size(C, 1), size(D, 1));
if isempty(C)
C = eye(new_row_for_C_or_D, size(A, 1));
end
if (isempty(D) || isDZero)
D = zeros(new_row_for_C_or_D, size(B, 2));
end
end
%=============================================================================
function msg = checkABCDE(varargin)
narginchk(4, 5);
if (nargin == 5)
E = varargin{5};
else
E = [];
end
A = varargin{1};
B = varargin{2};
C = varargin{3};
D = varargin{4};

[mA, nA] = size(A);
[mB, nB] = size(B);
[mC, nC] = size(C);
[mD, nD] = size(D);
[mE, nE] = size(E);

msg.message = '';
msg.identifier = '';
msg = msg(zeros(0, 1));

if (mA ~= nA)
msg.message = _('Matrix A must be square.');
msg.identifier = 'Nelson:control_system:AMustBeSquare';
return
end

if (mB ~= mA)
msg.message = _('The number of rows in matrices A and B must be equal.');
msg.identifier = 'Nelson:control_system:AAndBNumRowsMismatch';
return
end

if (nC ~= nA)
msg.message = _('Matrices A and C should have an identical number of columns.');
msg.identifier = 'Nelson:control_system:AAndCNumColumnsMismatch';
return
end

if (nB ~= nD)
msg.message = _('Matrices B and D should have an identical number of columns.');
msg.identifier = 'Nelson:control_system:BAndDNumColumnsMismatch';
return
end

if (mC ~= mD)
msg.message = _('The number of rows in matrices C and D must be equal.');
msg.identifier = 'Nelson:control_system:CAndDNumRowsMismatch';
return
end

if ~isempty(E) && (mA ~= mE || nA ~= nE)
msg.message = _('Matrices A and E should have an identical size.');
msg.identifier = 'Nelson:control_system:AAndESizeMismatch';
end
end
%=============================================================================
172 changes: 169 additions & 3 deletions modules/control_system/functions/@tf/tf.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%=============================================================================
% Copyright (c) 2017 September Daniel Mårtensson (Swedish Embedded Control Systems Toolbox)
% Copyright (c) 2023-present Allan CORNET (Nelson)
%=============================================================================
% This file is part of the Nelson.
Expand All @@ -7,7 +8,172 @@
% SPDX-License-Identifier: LGPL-3.0-or-later
% LICENCE_BLOCK_END
%=============================================================================
function sysOut = tf(sysIn)
sysOut = sysIn;
function varargout = tf(varargin)
narginchk(0, 3);
nargoutchk(0, 1);
sys = [];
if (nargin == 0)
sys = tf_no_rhs();
end
if (nargin == 1)
sys = tf_one_rhs(varargin{1});
end
if (nargin == 2)
Ts = 0;
[numeratorerator, denominator, variableName] = adjustTransferFunctionParameters(varargin{1}, varargin{2}, Ts);
sys = tf_constructor(numeratorerator, denominator, Ts, variableName);
end
if (nargin == 3)
Ts = varargin{3};
[numeratorerator, denominator, variableName] = adjustTransferFunctionParameters(varargin{1}, varargin{2}, Ts);
sys = tf_constructor(numeratorerator, denominator, Ts, variableName);
end
if (~isa(sys, 'tf'))
error(_('Wrong number of input arguments.'));
end
varargout{1} = sys;
end
%=============================================================================
%=============================================================================
function sys = tf_no_rhs()
tf = {};
tf.Numerator = {};
tf.Denominator= {};
tf.Variable = 's';
tf.Ts = 0;
tf.TimeUnit = 'seconds';
tf.UserData = [];
tf.Internal = [];
tf.Internal.Version = 1;
sys = class(tf, 'tf');
end
%=============================================================================
function sys = tf_one_rhs(m)
if islti(m)
if isa(m, 'tf')
sys = m;
elseif isa(m, 'ss')
error(_('Supported LTI model expected.'))
else
error(_('Supported LTI model expected.'))
end
return,
elseif ~isnumeric(m)
error('numeric value expected.');
end
sys = tf_no_rhs();
sys.Denominator = num2cell(ones(size(m)));
sys.Numerator = num2cell(m);
sys.Ts = -2;
end
%=============================================================================
function modifiedPart = checkFractionPart(part)
if iscell(part)
if isvector(part)
part = part(:)';
else
error(_('Invalid syntax.'));
end
elseif isnumeric(part)
if isvector(part) || isempty(part)
part = part(:)';
part = {part};
else
error(_('Invalid syntax.'));
end
else
error(_('Invalid syntax.'));
end
for j = 1:length(part)
for i = 1:length(part{j})
if(or(part{j}(i) > 0, part{j}(i) < 0))
part{j} = part{j}(1, i:length(part{j}));
break;
end
end
end
modifiedPart = part;
end
%=============================================================================
function [v1, v2] = arrangeVectors(v1, v2)
v1 = v1(:)';
v2 = v2(:)';
lenV1 = length(v1);
lenV2 = length(v2);
if lenV2 ~= lenV1
if (lenV2 > lenV1)
lenDiff = lenV2 - lenV1;
v1 = [zeros(1, lenDiff) , v1];
end
if (lenV2 < lenV1)
lenDiff = lenV1 - lenV2;
v2 = [zeros(1, lenDiff) , v2];
end
end
end
%=============================================================================
function [numerator, denominator, variableName] = adjustTransferFunctionParameters(numerator, denominator, Ts)
variableName = '';
isStaticGain = false;
if (isempty(denominator))
if (isempty(numerator))
numerator = {};
denominator = {};
isStaticGain = true;
elseif (isnumeric(numerator) && ismatrix(numerator) && isreal(numerator))
numerator = num2cell(numerator);
denominator = num2cell(ones(size(numerator)));
isStaticGain = true;
end
end

if (~iscell (numerator))
numerator = {numerator};
end
if (~iscell (denominator))
denominator = {denominator};
end
checkisAllZerosFunction = @(x) all(x == 0.);
isAllZeroNumerator = all(cellfun(checkisAllZerosFunction, numerator));
isAllZeroDenominator = all(cellfun(checkisAllZerosFunction, denominator));

checkisScalarFunction = @(x) (find (x ~= 0, 1) == length (x)) || (length (find (x ~= 0, 1)) == 0);
isAllScalarNumerator = ~isAllZeroNumerator && all(cellfun(checkisScalarFunction, numerator));
isAllScalarDenominator = ~isAllZeroDenominator && all(cellfun(checkisScalarFunction, denominator));
if (all (isAllScalarNumerator) && all(isAllScalarDenominator))
isStaticGain = true;
end
if (isStaticGain || (Ts == 0))
variableName = 's';
else
variableName = 'z';
end
end
%=============================================================================
function sys = tf_constructor(numeratorerator, denominator, Ts, variableName)
numeratorerator = checkFractionPart(numeratorerator);
denominator = checkFractionPart(denominator);
if (length(numeratorerator) == 1)
for k = 2:length(denominator)
numeratorerator{k} = numeratorerator{1};
end
end
if (length(denominator) == 1)
for k = 2:length(numeratorerator)
denominator{k} = denominator{1};
end
end
if (length(numeratorerator) ~= length(denominator))
error(_('Numerator and Denominator must have compatible sizes.'));
end
for k = 1:length(numeratorerator)
[N, D] = arrangeVectors(numeratorerator{k}, denominator{k});
numeratorerator{k} = N;
denominator{k} = D;
end
sys = tf_no_rhs();
sys.Denominator = denominator;
sys.Numerator = numeratorerator;
sys.Variable = variableName;
sys.Ts = Ts;
end
%=============================================================================
Loading

0 comments on commit 855c7f7

Please sign in to comment.