When I create a system using the python-control package:
import control
H = control.tf([1], [1])
And then want to iteratively simulate that system, how do I do it?
I know I can do this:
T = np.arange(0, 10, 0.01)
u = np.sin(T)
y, t, x = control.lsim(H, u, T)
But what I want to do is this:
Tstart = get_current_time() # returns a scalar
T = get_current_time()
x = None
while T - Tstart < 100:
u = get_next_input() # returns a scalar
T = get_current_time()
y, x = control.step_system(H, u, T, x)
do_something_with_output(y)
Is there some way I can do this? How else are you supposed to use a system developed with the control package to, you know, control something?
This is a great question. I am interested in this myself and asked a similar question on the Mathworks forum a while ago and it's not currently possible in MATLAB.
The good news is, you can now do it in Python Control using the iosys module and the input_output_response
function.
For a linear system as in your example you use the LinearIOSystem
class
Here is my simulation example:
import time
import numpy as np
import matplotlib.pyplot as plt
import control
from control import input_output_response
from control.iosys import LinearIOSystem
# Define system
# Continuous-time transfer function
G = control.tf([1], [2, 1])
# Convert to state-space representation
Gss = control.ss(G)
# Construct IO system
sys = LinearIOSystem(Gss, inputs='u', outputs='y')
def get_next_input(u, avg_time=0.5):
"""Function to simulate data acquisition"""
t0 = time.time()
wait_time = avg_time*(0.5 + np.random.rand())
while time.time() - t0 < wait_time:
pass
if np.random.rand() > 0.8:
u = u + np.random.randn()
return u
# Simulate system in response to irregular inputs
t0 = time.time()
t = 0
y0 = 0
u = 0
x = np.zeros(sys.nstates)
np.random.seed(1)
sim_results = [[0, u, y0]]
print(sim_results[-1])
while t < 10:
u_new, t_new = get_next_input(u), time.time() - t0
# Simulation of system up to current time
T_sim = [t, t_new]
T_sim, Y_sim, X_sim = input_output_response(sys, T_sim, u, X0=x,
return_x=True)
sim_results.append([T_sim[-1], u_new, Y_sim[-1]])
print(sim_results[-1])
# Set current state and outputs to end of simulation period
x = X_sim[0, -1]
u = u_new
t = t_new
sim_results = np.array(sim_results)
t = sim_results[:, 0]
u = sim_results[:, 1]
y = sim_results[:, 2]
# Plot inputs and outputs
plt.subplot(2, 1, 1)
plt.plot(t, y, 'o-')
plt.xlabel('t')
plt.ylabel('y(t)')
plt.grid()
plt.subplot(2, 1, 2)
plt.step(t, u, where='post')
plt.xlabel('t')
plt.ylabel('u(t)')
plt.grid()
plt.show()
In answer to your final question:
How else are you supposed to use a system developed with the control package to, you know, control something?"
I think tools like the MATLAB control module and python-control are intended to be used for the analysis, design and simulation of control systems, not necessarily for their implementation. Depending on your application, usually the final control system implementation is done on specialized hardware and/or software or might be hand-coded in a low-level language like C for example. High-level languages like MATLAB and Python are arguably too unreliable and difficult to maintain/upgrade for them to be attractive solutions in any serious process control or real-world robotics application. But for hobbyists and laboratory experiments they are ideal and so I agree this kind of functionality is useful.