|
37 | 37 | # SUCH DAMAGE.
|
38 | 38 |
|
39 | 39 | import numpy as np
|
| 40 | +from ..timeresp import TimeResponseData |
40 | 41 |
|
41 | 42 | class SystemTrajectory:
|
42 | 43 | """Class representing a system trajectory.
|
@@ -117,3 +118,75 @@ def eval(self, tlist):
|
117 | 118 | self.system.reverse(zflag, self.params)
|
118 | 119 |
|
119 | 120 | return xd, ud
|
| 121 | + |
| 122 | + # Return the system trajectory as a TimeResponseData object |
| 123 | + def response(self, tlist, transpose=False, return_x=False, squeeze=None): |
| 124 | + """Return the trajectory of a system as a TimeResponseData object |
| 125 | +
|
| 126 | + Evaluate the trajectory at a list of time points, returning the state |
| 127 | + and input vectors for the trajectory: |
| 128 | +
|
| 129 | + response = traj.response(tlist) |
| 130 | + time, yd, ud = response.time, response.outputs, response.inputs |
| 131 | +
|
| 132 | + Parameters |
| 133 | + ---------- |
| 134 | + tlist : 1D array |
| 135 | + List of times to evaluate the trajectory. |
| 136 | +
|
| 137 | + transpose : bool, optional |
| 138 | + If True, transpose all input and output arrays (for backward |
| 139 | + compatibility with MATLAB and :func:`scipy.signal.lsim`). |
| 140 | + Default value is False. |
| 141 | +
|
| 142 | + return_x : bool, optional |
| 143 | + If True, return the state vector when assigning to a tuple |
| 144 | + (default = False). See :func:`forced_response` for more details. |
| 145 | +
|
| 146 | + squeeze : bool, optional |
| 147 | + By default, if a system is single-input, single-output (SISO) then |
| 148 | + the output response is returned as a 1D array (indexed by time). |
| 149 | + If squeeze=True, remove single-dimensional entries from the shape |
| 150 | + of the output even if the system is not SISO. If squeeze=False, |
| 151 | + keep the output as a 3D array (indexed by the output, input, and |
| 152 | + time) even if the system is SISO. The default value can be set |
| 153 | + using config.defaults['control.squeeze_time_response']. |
| 154 | +
|
| 155 | + Returns |
| 156 | + ------- |
| 157 | + results : TimeResponseData |
| 158 | + Time response represented as a :class:`TimeResponseData` object |
| 159 | + containing the following properties: |
| 160 | +
|
| 161 | + * time (array): Time values of the output. |
| 162 | +
|
| 163 | + * outputs (array): Response of the system. If the system is SISO |
| 164 | + and squeeze is not True, the array is 1D (indexed by time). If |
| 165 | + the system is not SISO or ``squeeze`` is False, the array is 3D |
| 166 | + (indexed by the output, trace, and time). |
| 167 | +
|
| 168 | + * states (array): Time evolution of the state vector, represented |
| 169 | + as either a 2D array indexed by state and time (if SISO) or a 3D |
| 170 | + array indexed by state, trace, and time. Not affected by |
| 171 | + ``squeeze``. |
| 172 | +
|
| 173 | + * inputs (array): Input(s) to the system, indexed in the same |
| 174 | + manner as ``outputs``. |
| 175 | +
|
| 176 | + The return value of the system can also be accessed by assigning |
| 177 | + the function to a tuple of length 2 (time, output) or of length 3 |
| 178 | + (time, output, state) if ``return_x`` is ``True``. |
| 179 | +
|
| 180 | + """ |
| 181 | + # Compute the state and input response using the eval function |
| 182 | + sys = self.system |
| 183 | + xout, uout = self.eval(tlist) |
| 184 | + yout = np.array([ |
| 185 | + sys.output(tlist[i], xout[:, i], uout[:, i]) |
| 186 | + for i in range(len(tlist))]).transpose() |
| 187 | + |
| 188 | + return TimeResponseData( |
| 189 | + tlist, yout, xout, uout, issiso=sys.issiso(), |
| 190 | + input_labels=sys.input_labels, output_labels=sys.output_labels, |
| 191 | + state_labels=sys.state_labels, |
| 192 | + transpose=transpose, return_x=return_x, squeeze=squeeze) |
0 commit comments