Merge pull request #1019 from murrayrm/nlsys_improvements-24May2024 · python-control/python-control@6406868

@@ -54,17 +54,19 @@

5454

"""

55555656

from functools import reduce

57-

import numpy as np

5857

from warnings import warn

59-

from . import xferfcn as tf

60-

from . import statesp as ss

58+59+

import numpy as np

60+6161

from . import frdata as frd

62+

from . import statesp as ss

63+

from . import xferfcn as tf

6264

from .iosys import InputOutputSystem

63656466

__all__ = ['series', 'parallel', 'negate', 'feedback', 'append', 'connect']

6567666867-

def series(sys1, *sysn):

69+

def series(sys1, *sysn, **kwargs):

6870

r"""series(sys1, sys2, [..., sysn])

69717072

Return the series connection (`sysn` \* ...\ \*) `sys2` \* `sys1`.

@@ -79,6 +81,20 @@ def series(sys1, *sysn):

7981

out : scalar, array, or :class:`InputOutputSystem`

8082

Series interconnection of the systems.

818384+

Other Parameters

85+

----------------

86+

inputs, outputs : str, or list of str, optional

87+

List of strings that name the individual signals. If not given,

88+

signal names will be of the form `s[i]` (where `s` is one of `u`,

89+

or `y`). See :class:`InputOutputSystem` for more information.

90+

states : str, or list of str, optional

91+

List of names for system states. If not given, state names will be

92+

of of the form `x[i]` for interconnections of linear systems or

93+

'<subsys_name>.<state_name>' for interconnected nonlinear systems.

94+

name : string, optional

95+

System name (used for specifying signals). If unspecified, a generic

96+

name <sys[id]> is generated with a unique integer id.

97+8298

Raises

8399

------

84100

ValueError

@@ -117,10 +133,12 @@ def series(sys1, *sysn):

117133

(2, 1, 5)

118134119135

"""

120-

return reduce(lambda x, y: y * x, sysn, sys1)

136+

sys = reduce(lambda x, y: y * x, sysn, sys1)

137+

sys.update_names(**kwargs)

138+

return sys

121139122140123-

def parallel(sys1, *sysn):

141+

def parallel(sys1, *sysn, **kwargs):

124142

r"""parallel(sys1, sys2, [..., sysn])

125143126144

Return the parallel connection `sys1` + `sys2` (+ ...\ + `sysn`).

@@ -135,6 +153,20 @@ def parallel(sys1, *sysn):

135153

out : scalar, array, or :class:`InputOutputSystem`

136154

Parallel interconnection of the systems.

137155156+

Other Parameters

157+

----------------

158+

inputs, outputs : str, or list of str, optional

159+

List of strings that name the individual signals. If not given,

160+

signal names will be of the form `s[i]` (where `s` is one of `u`,

161+

or `y`). See :class:`InputOutputSystem` for more information.

162+

states : str, or list of str, optional

163+

List of names for system states. If not given, state names will be

164+

of of the form `x[i]` for interconnections of linear systems or

165+

'<subsys_name>.<state_name>' for interconnected nonlinear systems.

166+

name : string, optional

167+

System name (used for specifying signals). If unspecified, a generic

168+

name <sys[id]> is generated with a unique integer id.

169+138170

Raises

139171

------

140172

ValueError

@@ -171,10 +203,11 @@ def parallel(sys1, *sysn):

171203

(3, 4, 7)

172204173205

"""

174-

return reduce(lambda x, y: x + y, sysn, sys1)

175-206+

sys = reduce(lambda x, y: x + y, sysn, sys1)

207+

sys.update_names(**kwargs)

208+

return sys

176209177-

def negate(sys):

210+

def negate(sys, **kwargs):

178211

"""

179212

Return the negative of a system.

180213

@@ -188,15 +221,29 @@ def negate(sys):

188221

out : scalar, array, or :class:`InputOutputSystem`

189222

Negated system.

190223191-

Notes

192-

-----

193-

This function is a wrapper for the __neg__ function in the StateSpace and

194-

TransferFunction classes. The output type is the same as the input type.

224+

Other Parameters

225+

----------------

226+

inputs, outputs : str, or list of str, optional

227+

List of strings that name the individual signals. If not given,

228+

signal names will be of the form `s[i]` (where `s` is one of `u`,

229+

or `y`). See :class:`InputOutputSystem` for more information.

230+

states : str, or list of str, optional

231+

List of names for system states. If not given, state names will be

232+

of of the form `x[i]` for interconnections of linear systems or

233+

'<subsys_name>.<state_name>' for interconnected nonlinear systems.

234+

name : string, optional

235+

System name (used for specifying signals). If unspecified, a generic

236+

name <sys[id]> is generated with a unique integer id.

195237196238

See Also

197239

--------

198240

append, feedback, interconnect, parallel, series

199241242+

Notes

243+

-----

244+

This function is a wrapper for the __neg__ function in the StateSpace and

245+

TransferFunction classes. The output type is the same as the input type.

246+200247

Examples

201248

--------

202249

>>> G = ct.tf([2], [1, 1])

@@ -208,11 +255,12 @@ def negate(sys):

208255

np.float64(-2.0)

209256210257

"""

211-

return -sys

258+

sys = -sys

259+

sys.update_names(**kwargs)

260+

return sys

212261213262

#! TODO: expand to allow sys2 default to work in MIMO case?

214-

#! TODO: allow renaming of signals (for all bdalg operations)

215-

def feedback(sys1, sys2=1, sign=-1):

263+

def feedback(sys1, sys2=1, sign=-1, **kwargs):

216264

"""Feedback interconnection between two I/O systems.

217265218266

Parameters

@@ -229,6 +277,20 @@ def feedback(sys1, sys2=1, sign=-1):

229277

out : scalar, array, or :class:`InputOutputSystem`

230278

Feedback interconnection of the systems.

231279280+

Other Parameters

281+

----------------

282+

inputs, outputs : str, or list of str, optional

283+

List of strings that name the individual signals. If not given,

284+

signal names will be of the form `s[i]` (where `s` is one of `u`,

285+

or `y`). See :class:`InputOutputSystem` for more information.

286+

states : str, or list of str, optional

287+

List of names for system states. If not given, state names will be

288+

of of the form `x[i]` for interconnections of linear systems or

289+

'<subsys_name>.<state_name>' for interconnected nonlinear systems.

290+

name : string, optional

291+

System name (used for specifying signals). If unspecified, a generic

292+

name <sys[id]> is generated with a unique integer id.

293+232294

Raises

233295

------

234296

ValueError

@@ -261,7 +323,7 @@ def feedback(sys1, sys2=1, sign=-1):

261323

# Allow anything with a feedback function to call that function

262324

# TODO: rewrite to allow __rfeedback__

263325

try:

264-

return sys1.feedback(sys2, sign)

326+

return sys1.feedback(sys2, sign, **kwargs)

265327

except (AttributeError, TypeError):

266328

pass

267329

@@ -284,9 +346,11 @@ def feedback(sys1, sys2=1, sign=-1):

284346

else:

285347

sys1 = ss._convert_to_statespace(sys1)

286348287-

return sys1.feedback(sys2, sign)

349+

sys = sys1.feedback(sys2, sign)

350+

sys.update_names(**kwargs)

351+

return sys

288352289-

def append(*sys):

353+

def append(*sys, **kwargs):

290354

"""append(sys1, sys2, [..., sysn])

291355292356

Group LTI state space models by appending their inputs and outputs.

@@ -299,6 +363,20 @@ def append(*sys):

299363

sys1, sys2, ..., sysn: scalar, array, or :class:`StateSpace`

300364

I/O systems to combine.

301365366+

Other Parameters

367+

----------------

368+

inputs, outputs : str, or list of str, optional

369+

List of strings that name the individual signals. If not given,

370+

signal names will be of the form `s[i]` (where `s` is one of `u`,

371+

or `y`). See :class:`InputOutputSystem` for more information.

372+

states : str, or list of str, optional

373+

List of names for system states. If not given, state names will be

374+

of of the form `x[i]` for interconnections of linear systems or

375+

'<subsys_name>.<state_name>' for interconnected nonlinear systems.

376+

name : string, optional

377+

System name (used for specifying signals). If unspecified, a generic

378+

name <sys[id]> is generated with a unique integer id.

379+302380

Returns

303381

-------

304382

out: :class:`StateSpace`

@@ -327,6 +405,7 @@ def append(*sys):

327405

s1 = ss._convert_to_statespace(sys[0])

328406

for s in sys[1:]:

329407

s1 = s1.append(s)

408+

s1.update_names(**kwargs)

330409

return s1

331410332411

def connect(sys, Q, inputv, outputv):

@@ -370,6 +449,12 @@ def connect(sys, Q, inputv, outputv):

370449

--------

371450

append, feedback, interconnect, negate, parallel, series

372451452+

Notes

453+

-----

454+

The :func:`~control.interconnect` function in the :ref:`input/output

455+

systems <iosys-module>` module allows the use of named signals and

456+

provides an alternative method for interconnecting multiple systems.

457+373458

Examples

374459

--------

375460

>>> G = ct.rss(7, inputs=2, outputs=2)

@@ -378,12 +463,6 @@ def connect(sys, Q, inputv, outputv):

378463

>>> T.ninputs, T.noutputs, T.nstates

379464

(1, 2, 7)

380465381-

Notes

382-

-----

383-

The :func:`~control.interconnect` function in the :ref:`input/output

384-

systems <iosys-module>` module allows the use of named signals and

385-

provides an alternative method for interconnecting multiple systems.

386-387466

"""

388467

# TODO: maintain `connect` for use in MATLAB submodule (?)

389468

warn("`connect` is deprecated; use `interconnect`", DeprecationWarning)