From 5236265e7231a7ecfac9cac49ef2687e210bc464 Mon Sep 17 00:00:00 2001 From: Allan CORNET Date: Tue, 26 Sep 2023 21:42:55 +0200 Subject: [PATCH] fix #968 zp2tf function --- CHANGELOG.md | 1 + modules/signal_processing/functions/zp2tf.m | 63 +++++++++++++++ .../help/en_US/xml/zp2tf.xml | 79 +++++++++++++++++++ modules/signal_processing/tests/test_zp2tf.m | 35 ++++++++ 4 files changed, 178 insertions(+) create mode 100644 modules/signal_processing/functions/zp2tf.m create mode 100644 modules/signal_processing/help/en_US/xml/zp2tf.xml create mode 100644 modules/signal_processing/tests/test_zp2tf.m diff --git a/CHANGELOG.md b/CHANGELOG.md index 24acac82b3..e37fcd312f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - [#967](http://github.com/Nelson-numerical-software/nelson/issues/967) control system module template. - `abcdchk` Verifies the dimensional compatibility of matrices A, B, C, and D. - [#944](http://github.com/Nelson-numerical-software/nelson/issues/944) `mag2db`, `db2mag`, `pow2db`, `db2pow` functions. + - [#968](http://github.com/Nelson-numerical-software/nelson/issues/968) `zp2tf`: Zero-pole to transfer function conversion. ### Changed diff --git a/modules/signal_processing/functions/zp2tf.m b/modules/signal_processing/functions/zp2tf.m new file mode 100644 index 0000000000..eec514f931 --- /dev/null +++ b/modules/signal_processing/functions/zp2tf.m @@ -0,0 +1,63 @@ +%============================================================================= +% Copyright (c) 2016-present Allan CORNET (Nelson) +%============================================================================= +% This file is part of the Nelson. +%============================================================================= +% LICENCE_BLOCK_BEGIN +% SPDX-License-Identifier: LGPL-3.0-or-later +% LICENCE_BLOCK_END +%============================================================================= +function varargout = zp2tf(varargin) + narginchk(3, 3); + nargoutchk(0, 2); + z = varargin{1}; + p = varargin{2}; + k = varargin{3}; + + den = computesDenominator(p); + varargout{1} = computesNumerator(z, k, den); + + if nargout > 1 + varargout{2} = den; + end +end +%============================================================================= +function den = computesDenominator(p) + den = real(poly(p(:))); +end +%============================================================================= +function num = computesNumerator(z, k, den) + num = []; + denc = size(den, 2); + k = k(:); + kr = size(k, 1); + if isempty(z) + if (denc - 1 > 0) + num = [zeros(kr, denc - 1), k]; + else + num = k; + end + else + zc = size(z, 2); + if kr ~= zc + if ((size(z, 1) - 1) ~= 0) + error('Input argument #1 and #3 should have the same column size.'); + else + error('First argument must be a column vector.'); + end + else + num = []; + for nidx = 1:zc + zidx = z(:, nidx); + pidx = real(poly(zidx) * k(nidx)); + zr = zeros(1, denc - length(pidx)); + if isempty(num) + num = [zr, pidx]; + else + num(nidx, :) = [zr, pidx]; + end + end + end + end +end +%============================================================================= diff --git a/modules/signal_processing/help/en_US/xml/zp2tf.xml b/modules/signal_processing/help/en_US/xml/zp2tf.xml new file mode 100644 index 0000000000..c9ac44d884 --- /dev/null +++ b/modules/signal_processing/help/en_US/xml/zp2tf.xml @@ -0,0 +1,79 @@ + + + SAME AS NELSON SOFTWARE + + en_US + zp2tf + Zero-pole to transfer function conversion. + + + [NUM, DEN] = zp2tf(Z, P, K) + + + + + Z + Locations of zeros, organized in columns for each system output. + + + P + Locations of poles, recorded as a column vector. + + + K + Gains. + + + + + + + NUM + Coefficients in the numerator, organized by rows corresponding to each system output. + + + DEN + Coefficients in the denominator, arranged as a row vector. + + + + +

[NUM, DEN] = zp2tf(Z, P, K) returns polynomial transfer function representation from zeros and poles.

+
+ + + + nelson + + + + + + + + + tf2zpk + + + + + + 1.0.0 + initial version + + + + + Allan CORNET + +
diff --git a/modules/signal_processing/tests/test_zp2tf.m b/modules/signal_processing/tests/test_zp2tf.m new file mode 100644 index 0000000000..3cc6cf869d --- /dev/null +++ b/modules/signal_processing/tests/test_zp2tf.m @@ -0,0 +1,35 @@ +%============================================================================= +% Copyright (c) 2016-present Allan CORNET (Nelson) +%============================================================================= +% This file is part of the Nelson. +%============================================================================= +% LICENCE_BLOCK_BEGIN +% SPDX-License-Identifier: LGPL-3.0-or-later +% LICENCE_BLOCK_END +%============================================================================= +assert_isequal(nargin('zp2tf'), -1); +assert_isequal(nargout('zp2tf'), -1); +%============================================================================= +assert_checkerror('zp2tf([-100 -2.01], [-5 -.9 -20.1], 1)', _('First argument must be a column vector.')) +%============================================================================= +[N, D] = zp2tf([-1; -2.01], [-5 -9.9 -20.1], 1); +N_REF = [0 1.0000 3.0100 2.0100]; +D_REF = [1.0000 35.0000 348.9900 994.9500]; +assert_isapprox(N, N_REF, 1e-3); +assert_isapprox(D, D_REF, 1e-3); +%============================================================================= +[N, D] = zp2tf([], [], 1); +N_REF = 1; +D_REF = 1; +assert_isequal(N, N_REF); +assert_isequal(D, D_REF); +%============================================================================= +z = [49.498, 0; -49.498, 16.362]; +p = [0; -57.753; 53.851; 2.0831]; +k = [18.182; 45.455]; +[N, D] = zp2tf(z, p, k); +N_REF = 1.0e+04 * [0, 0, 0.0018, 0, -4.4547; 0, 0, 0.0045, -0.0744, 0]; +D_REF = 1.0e+03 * [0.0010, 0.0018, -3.1182, 6.4786, 0]; +assert_isapprox(N, N_REF, 1e-3); +assert_isapprox(D, D_REF, 1e-3); +%=============================================================================