-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinitial_data_generation.py
More file actions
227 lines (186 loc) · 8.89 KB
/
Copy pathinitial_data_generation.py
File metadata and controls
227 lines (186 loc) · 8.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
"""
Functions for generating initial input-output data from a system.
This module provides functions for generating input-output data from both LTI
and nonlinear systems, and randomizing the initial state of LTI systems.
"""
import numpy as np
from numpy.random import Generator
from direct_data_driven_mpc.utilities.models import (
LTIModel,
NonlinearSystem,
)
from .controller_params import (
DataDrivenMPCParams,
LTIDataDrivenMPCParams,
)
def randomize_initial_system_state(
system_model: LTIModel,
controller_config: LTIDataDrivenMPCParams,
np_random: Generator,
) -> np.ndarray:
"""
Randomly generate a plausible initial state for a Linear Time-Invariant
(LTI) system model.
This function initializes the system state with random values within the
[-1, 1] range. Afterward, it simulates the system using random input and
noise sequences to generate an input-output trajectory, which is then used
to estimate the initial system state.
Note:
The random input sequence is generated based on the `u_range`
parameter from the controller configuration (`controller_config`). The
noise sequence is generated considering the defined noise bounds from
the system.
Args:
system_model (LTIModel): An `LTIModel` instance representing a Linear
Time-Invariant (LTI) system.
controller_config (LTIDataDrivenMPCParams): A dictionary containing
parameters for a Data-Driven MPC controller designed for Linear
Time-Invariant (LTI) systems, including the range of the
persistently exciting input (`u_range`).
np_random (Generator): A Numpy random number generator for generating
the random initial system state, persistently exciting input, and
system output noise.
Returns:
np.ndarray: A vector of shape `(n, )` representing the estimated
initial state of the system, where `n` is the system's order.
"""
# Retrieve model parameters
ns = system_model.n # System order (simulation)
m = system_model.m # Number of inputs
p = system_model.p # Number of outputs
eps_max_sim = system_model.eps_max # Upper bound of the system
# measurement noise (simulation)
# Retrieve Data-Driven MPC controller parameters
u_range = controller_config["u_range"] # Range of the persistently
# exciting input u_d
# Randomize initial system state before excitation
x_i0 = np_random.uniform(-1.0, 1.0, size=ns)
assert isinstance(x_i0, np.ndarray) # Prevent mypy [arg-type] error
system_model.set_state(state=x_i0)
# Generate a random input array
u_i = np.hstack(
[
np_random.uniform(u_range[i, 0], u_range[i, 1], (ns, 1))
for i in range(m)
]
)
# Generate bounded uniformly distributed additive measurement noise
w_i = eps_max_sim * np_random.uniform(-1.0, 1.0, (ns, p))
# Simulate the system with the generated random input and noise
# sequences to obtain output data
y_i = system_model.simulate(U=u_i, W=w_i, steps=ns)
# Calculate the initial state of the system
# from the input-output trajectory
x_0 = system_model.get_initial_state_from_trajectory(
U=u_i.flatten(), Y=y_i.flatten()
)
return x_0
def generate_initial_input_output_data(
system_model: LTIModel | NonlinearSystem,
controller_config: DataDrivenMPCParams,
np_random: Generator,
) -> tuple[np.ndarray, np.ndarray]:
"""
Generate input-output trajectory data from a system using Data-Driven MPC
controller parameters.
This function generates a persistently exciting input `u_d` and random
noise based on the specified controller and system parameters. Then, it
simulates the system using these input and noise sequences to generate the
output response `y_d`. The resulting `u_d` and `y_d` arrays represent the
input-output trajectory data measured from the system, which is necessary
for system characterization in a Data-Driven MPC formulation.
Args:
system_model (LTIModel | NonlinearSystem): An instance of `LTIModel`,
representing a Linear Time-Invariant (LTI) system, or
`NonlinearSystem`, representing a nonlinear system.
controller_config (DataDrivenMPCParams): A dictionary containing
parameters for a Data-Driven MPC controller designed for Linear
Time-Invariant (LTI) or nonlinear systems. Includes the initial
input-output trajectory length (`N`) and the range of the
persistently exciting input (`u_range`).
np_random (Generator): A Numpy random number generator for generating
the persistently exciting input and random noise for the system's
output.
Returns:
tuple[np.ndarray, np.ndarray]: A tuple containing two arrays: a
persistently exciting input (`u_d`) and the system's output response
(`y_d`). The input array has shape `(N, m)` and the output array has
shape `(N, p)`, where `N` is the trajectory length, `m` is the number
of control inputs, and `p` is the number of system outputs.
"""
# Retrieve model parameters
m = system_model.m # Number of inputs
p = system_model.p # Number of outputs
eps_max_sim = system_model.eps_max # Upper bound of the system
# measurement noise (simulation)
# Retrieve Data-Driven MPC controller parameters
N = controller_config["N"] # Initial input-output trajectory length
u_range = controller_config["u_range"] # Range of the persistently
# exciting input u_d
# Generate a persistently exciting input `u_d` from 0 to (N - 1)
u_d = np.hstack(
[
np_random.uniform(u_range[i, 0], u_range[i, 1], (N, 1))
for i in range(m)
]
)
# Generate bounded uniformly distributed additive measurement noise
w_d = eps_max_sim * np_random.uniform(-1.0, 1.0, (N, p))
# Simulate the system with the persistently exciting input `u_d` and
# the generated noise sequence to obtain output data
y_d = system_model.simulate(U=u_d, W=w_d, steps=N)
return u_d, y_d
def simulate_n_input_output_measurements(
system_model: LTIModel,
controller_config: LTIDataDrivenMPCParams,
np_random: Generator,
) -> tuple[np.ndarray, np.ndarray]:
"""
Simulate a control input setpoint applied to a system over `n` (the
estimated system order) time steps and return the resulting input-output
data sequences.
This function retrieves the control input setpoint (`u_s`) and the
estimated system order (`n`) from a Data-Driven MPC controller
configuration. Then, it simulates the system using a constant input `u_s`
and random output noise over `n` time steps. The resulting input-output
trajectory can be used to update the past `n` input-output measurements
of a previously initialized Data-Driven MPC controller, allowing it to
operate on a system with a different state.
Note:
This function is used for scenarios where a Data-Driven MPC controller
has been initialized but needs to be adjusted to match different
system states.
Args:
system_model (LTIModel): An `LTIModel` instance representing a Linear
Time-Invariant (LTI) system.
controller_config (LTIDataDrivenMPCParams): A dictionary containing
parameters for a Data-Driven MPC controller designed for Linear
Time-Invariant (LTI) systems, including the estimated system order
(`n`) and the control input setpoint (`u_s`).
np_random (Generator): A Numpy random number generator for generating
random noise for the system's output.
Returns:
tuple[np.ndarray, np.ndarray]: A tuple containing two arrays:
- An array of shape `(n, m)` representing the constant input setpoint
applied to the system over `n` time steps, where `n` is the system
order and `m` is the number of control inputs.
- An array of shape `(n, p)` representing the output response of the
system, where `n` is the system order and `p` is the number of system
outputs.
"""
# Retrieve model parameters
m = system_model.m # Number of inputs
p = system_model.p # Number of outputs
eps_max_sim = system_model.eps_max # Upper bound of the system
# measurement noise
# Retrieve Data-Driven MPC controller parameters
n = controller_config["n"] # Estimated system order
u_s = controller_config["u_s"] # Control input setpoint
# Construct input array from controller's input setpoint
U_n = np.tile(u_s, (n, 1)).reshape(n, m)
# Generate bounded uniformly distributed additive measurement noise
W_n = eps_max_sim * np_random.uniform(-1.0, 1.0, (n, p))
# Simulate the system with the constant input and generated
# noise sequences
Y_n = system_model.simulate(U=U_n, W=W_n, steps=n)
return U_n, Y_n