http://fbswiki.org/wiki/api.php?action=feedcontributions&user=Murray&feedformat=atom FBSwiki - User contributions [en] 2021-09-26T13:54:58Z User contributions MediaWiki 1.35.1 http://fbswiki.org/wiki/index.php?title=File:Figure-3.28-fitzhugh_nagumo.png&diff=753 File:Figure-3.28-fitzhugh nagumo.png 2021-08-31T05:19:21Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.28:_Response_of_a_neuron_to_a_current_input&diff=752 Figure 3.28: Response of a neuron to a current input 2021-08-31T05:19:12Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=28<br /> |Figure title=Response of a neuron to a current input<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.19-fitzhugh_nagumo.py<br /> }}<br /> [[Image:figure-3.28-fitzhugh_nagumo.png|640px]]<br /> <br /> '''Figure 3.28:''' Response of a neuron to a current input. The current input is shown in (a) and the neuron voltage V in (b). The simulation was done using the FitzHugh–Nagumo model (Exercise 3.11).<br /> <br /> &lt;nowiki&gt;<br /> # example-3.19-fitzhugh_nagumo.py - nerve cell dynamics<br /> # RMM, 30 Aug 2021<br /> #<br /> # Figure 3.28: Response of a neuron to a current input. The current<br /> # input is shown in (a) and the neuron voltage V in (b). The<br /> # simulation was done using the FitzHugh–Nagumo model (Exercise 3.11).<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> ct.use_fbs_defaults()<br /> <br /> #<br /> # System dynamics<br /> #<br /> <br /> # FitzHugh-Nagumo dynamics (from KJA)<br /> def fitzhugh_nagumo_dynamics(t, x, u, params):<br /> dx = np.zeros(3)<br /> <br /> # Get the system state<br /> V = x<br /> R = x<br /> <br /> # Compute the dim derivative<br /> dx = 10 * (V - (V**3) / 3 - R + u)<br /> dx = 0.8 * (-R + 1.25 * V + 1.5)<br /> dx = 1<br /> <br /> return dx<br /> <br /> # Set up an input/output system<br /> sys = ct.NonlinearIOSystem(<br /> updfcn=fitzhugh_nagumo_dynamics, states=3, inputs=1, outputs=3)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (a) Current input<br /> #<br /> <br /> fig.add_subplot(gs[0, 0]) # first row, first column<br /> <br /> # Set up input stimulation<br /> t = np.linspace(0, 50, 500)<br /> u = np.zeros_like(t)<br /> u[t &gt;= 5] = 1.5 # start of short input pulse<br /> u[t &gt;= 6] = 0 # end of short input pulse<br /> u[t &gt;= 30] = 1.5 # longer input pulse<br /> <br /> # Initial state<br /> x0 = [-1.5, -3/8, 0]<br /> <br /> response = ct.input_output_response(sys, t, u, x0)<br /> <br /> plt.plot(response.time, response.inputs)<br /> plt.xlabel(&quot;Time $t$ [ms]&quot;)<br /> plt.ylabel(&quot;Current $I$ [mA]&quot;)<br /> plt.title(&quot;Input stimulation&quot;)<br /> <br /> #<br /> # (b) Neuron response<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, second column<br /> <br /> plt.plot(response.time, response.states)<br /> plt.xlabel(&quot;Time $t$ [ms]&quot;)<br /> plt.ylabel(&quot;Voltage $V$ [mV]&quot;)<br /> plt.title(&quot;Neuron response&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.19-fitzhugh_nagumo.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.28:_Response_of_a_neuron_to_a_current_input&diff=751 Figure 3.28: Response of a neuron to a current input 2021-08-31T05:18:13Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=28 |Figure title=Response of a neuron to a current input |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/exampl...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=28<br /> |Figure title=Response of a neuron to a current input<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.19-fitzhugh_nagumo.py<br /> }}<br /> [[Image:figure-3.28-fitzhugh_nagumo.py|640px]]<br /> <br /> '''Figure 3.28:''' Response of a neuron to a current input. The current input is shown in (a) and the neuron voltage V in (b). The simulation was done using the FitzHugh–Nagumo model (Exercise 3.11).<br /> <br /> &lt;nowiki&gt;<br /> # example-3.19-fitzhugh_nagumo.py - nerve cell dynamics<br /> # RMM, 30 Aug 2021<br /> #<br /> # Figure 3.28: Response of a neuron to a current input. The current<br /> # input is shown in (a) and the neuron voltage V in (b). The<br /> # simulation was done using the FitzHugh–Nagumo model (Exercise 3.11).<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> ct.use_fbs_defaults()<br /> <br /> #<br /> # System dynamics<br /> #<br /> <br /> # FitzHugh-Nagumo dynamics (from KJA)<br /> def fitzhugh_nagumo_dynamics(t, x, u, params):<br /> dx = np.zeros(3)<br /> <br /> # Get the system state<br /> V = x<br /> R = x<br /> <br /> # Compute the dim derivative<br /> dx = 10 * (V - (V**3) / 3 - R + u)<br /> dx = 0.8 * (-R + 1.25 * V + 1.5)<br /> dx = 1<br /> <br /> return dx<br /> <br /> # Set up an input/output system<br /> sys = ct.NonlinearIOSystem(<br /> updfcn=fitzhugh_nagumo_dynamics, states=3, inputs=1, outputs=3)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (a) Current input<br /> #<br /> <br /> fig.add_subplot(gs[0, 0]) # first row, first column<br /> <br /> # Set up input stimulation<br /> t = np.linspace(0, 50, 500)<br /> u = np.zeros_like(t)<br /> u[t &gt;= 5] = 1.5 # start of short input pulse<br /> u[t &gt;= 6] = 0 # end of short input pulse<br /> u[t &gt;= 30] = 1.5 # longer input pulse<br /> <br /> # Initial state<br /> x0 = [-1.5, -3/8, 0]<br /> <br /> response = ct.input_output_response(sys, t, u, x0)<br /> <br /> plt.plot(response.time, response.inputs)<br /> plt.xlabel(&quot;Time $t$ [ms]&quot;)<br /> plt.ylabel(&quot;Current $I$ [mA]&quot;)<br /> plt.title(&quot;Input stimulation&quot;)<br /> <br /> #<br /> # (b) Neuron response<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, second column<br /> <br /> plt.plot(response.time, response.states)<br /> plt.xlabel(&quot;Time $t$ [ms]&quot;)<br /> plt.ylabel(&quot;Voltage $V$ [mV]&quot;)<br /> plt.title(&quot;Neuron response&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.19-fitzhugh_nagumo.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.26-repressilator_dynamics.png&diff=750 File:Figure-3.26-repressilator dynamics.png 2021-08-30T16:53:10Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.26:_The_repressilator_genetic_regulatory_network&diff=749 Figure 3.26: The repressilator genetic regulatory network 2021-08-30T16:52:52Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=36 |Figure title=The repressilator genetic regulatory network |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/e...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=36<br /> |Figure title=The repressilator genetic regulatory network<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.18-repressilator.py<br /> }}<br /> [[Image:figure-3.26-repressilator_dynamics.png|320px]]<br /> <br /> Figure 3.26: The repressilator genetic regulatory network. (b) A simulation of a simple model for the repressilator, showing the oscillation of the individual protein concentrations.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.18-repressilator.py - Transcriptional regulation<br /> # RMM, 29 Aug 2021<br /> #<br /> # Figure 3.26: The repressilator genetic regulatory network. (a) A schematic<br /> # diagram of the repressilator, showing the layout of the genes in the<br /> # plasmid that holds the circuit as well as the circuit diagram<br /> # (center). (b) A simulation of a simple model for the repressilator,<br /> # showing the oscillation of the individual protein concentrations.<br /> #<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> #<br /> # Repressilator dynamics<br /> #<br /> # This function implements the basic model of the repressilator All<br /> # parameter values were taken from Nature. 2000 Jan 20; 403(6767):335-8.<br /> #<br /> # This model was developed by members of the 2003 Synthetic Biology Class<br /> # on Engineered Blinkers.<br /> #<br /> <br /> # Dynamics for the repressilator<br /> def repressilator(t, x, u, params):<br /> # store the state variables under more meaningful names<br /> mRNA_cI = x<br /> mRNA_lacI = x<br /> mRNA_tetR = x<br /> protein_cI = x<br /> protein_lacI = x<br /> protein_tetR = x<br /> <br /> #<br /> # set the parameter values<br /> #<br /> <br /> # set the max transcription rate in transcripts per second<br /> k_transcription_cI = params.get('k_transcription_cI', 0.5)<br /> k_transcription_lacI = params.get('k_transcription_lacI', 0.5)<br /> k_transcription_tetR = params.get('k_transcription_tetR', 0.5)<br /> <br /> # set the leakage transcription rate (ie transcription rate if<br /> # promoter region bound by repressor) in transcripts per second<br /> k_transcription_leakage = params.get('k_transcription_leakage', 5e-4)<br /> <br /> # Set the mRNA and protein degradation rates (per second)<br /> mRNA_half_life = params.get('mRNA_half_life', 120) # in seconds<br /> k_mRNA_degradation = np.log(2)/mRNA_half_life<br /> protein_half_life = params.get('protein_half_life', 600) # in seconds<br /> k_protein_degradation = np.log(2)/protein_half_life<br /> <br /> # proteins per transcript lifespan<br /> translation_efficiency = params.get('translation_efficiency', 20)<br /> average_mRNA_lifespan = 1/k_mRNA_degradation<br /> <br /> # proteins per transcript per sec<br /> k_translation = translation_efficiency/average_mRNA_lifespan <br /> <br /> # set the Hill coefficients of the repressors<br /> n_tetR = params.get('n_tetR', 2)<br /> n_cI = params.get('n_cI', 2)<br /> n_lacI = params.get('n_lacI', 2)<br /> <br /> # Set the dissociation constant for the repressors to their target promoters<br /> # in per molecule per second<br /> KM_tetR = params.get('KM_tetR', 40)<br /> KM_cI = params.get('KM_cI', 40)<br /> KM_lacI = params.get('KM_lacI', 40)<br /> <br /> # the differential equations governing the state variables:<br /> # mRNA concentration = transcription given repressor concentration - <br /> # mRNA degradation + transcription leakage<br /> dxdt = np.empty(6)<br /> dxdt = k_transcription_cI/(1 + (protein_tetR / KM_tetR) ** n_tetR) - \<br /> k_mRNA_degradation * mRNA_cI + k_transcription_leakage<br /> dxdt = k_transcription_lacI/(1 + (protein_cI / KM_cI)**n_cI) - \<br /> k_mRNA_degradation * mRNA_lacI + k_transcription_leakage<br /> dxdt = k_transcription_tetR/(1 + (protein_lacI / KM_lacI) ** n_lacI) - \<br /> k_mRNA_degradation * mRNA_tetR + k_transcription_leakage<br /> <br /> # protein concentration = translation - protein degradation<br /> dxdt = k_translation*mRNA_cI - k_protein_degradation*protein_cI<br /> dxdt = k_translation*mRNA_lacI - k_protein_degradation*protein_lacI<br /> dxdt = k_translation*mRNA_tetR - k_protein_degradation*protein_tetR<br /> <br /> return dxdt<br /> <br /> # Define the system as an I/O system<br /> sys = ct.NonlinearIOSystem(<br /> updfcn=repressilator, outfcn=lambda t, x, u, params: x[3:],<br /> states=6, inputs=0, outputs=3)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(2, 2)<br /> <br /> #<br /> # (b) A simulation of a simple model for the repressilator, showing the<br /> # oscillation of the individual protein concentrations.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, second column<br /> <br /> # Initial conditions and time<br /> t = np.linspace(0, 20000, 1000)<br /> x0 = [1, 0, 0, 200, 0, 0]<br /> <br /> # Integrate the differential equation<br /> response = ct.input_output_response(sys, t, 0, x0)<br /> <br /> # Plot the results (protein concentrations)<br /> plt.plot(response.time/60, response.outputs, '-')<br /> plt.plot(response.time/60, response.outputs, '--')<br /> plt.plot(response.time/60, response.outputs, '-.')<br /> <br /> plt.axis([0, 300, 0, 5000])<br /> plt.legend((&quot;cI&quot;, &quot;lacI&quot;, &quot;tetR&quot;), loc='upper right')<br /> <br /> plt.xlabel(&quot;Time [min]&quot;) # Axis labels<br /> plt.ylabel(&quot;Proteins per cell&quot;)<br /> plt.title(&quot;Repressilator simulation&quot;) # Plot title<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.26-repressilator_dynamics.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.24:_Consensus_protocols_for_sensor_networks&diff=748 Figure 3.24: Consensus protocols for sensor networks 2021-08-30T16:24:52Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=24<br /> |Figure title=Consensus protocols for sensor networks<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.17-consensus.py<br /> }}<br /> [[Image:figure-3.24-consensus_dynamics.png|320px]]<br /> <br /> Figure 3.24: Consensus protocols for sensor networks. (b) A simulation demonstrating the convergence of the consensus protocol (3.35) to the average value of the initial conditions.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.17-consensus.py - consensus protocols<br /> # RMM, 30 Aug 2021<br /> <br /> # Figure 3.24: Consensus protocols for sensor networks. (a) A simple sensor<br /> # net- work with five nodes. In this network, node 1 communicates with node<br /> # 2 and node 2 communicates with nodes 1, 3, 4, 5, etc. (b) A simulation<br /> # demonstrating the convergence of the consensus protocol (3.35) to the<br /> # average value of the initial conditions.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> #<br /> # System dynamcis<br /> #<br /> <br /> # Construct the Laplacian corresponding to our network<br /> L = np.array([<br /> [ 1, -1, 0, 0, 0],<br /> [-1, 4, -1, -1, -1],<br /> [ 0, -1, 2, -1, 0],<br /> [ 0, -1, -1, 2, 0],<br /> [ 0, -1, 0, 0, 1]<br /> ])<br /> <br /> # Now generate the discrete time dynamics matrix<br /> gamma = 0.1<br /> A = np.eye(5) - gamma * L<br /> <br /> # Initial set of measurements for the system<br /> x0 = [10, 15, 25, 35, 40]<br /> <br /> # Create a discrete time system<br /> sys = ct.ss(A, np.zeros(5), np.zeros(5), 0, dt=True)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (b) A simulation demonstrating the convergence of the consensus protocol<br /> # (3.35) to the average value of the initial conditions.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, first column<br /> <br /> # Simulate the system<br /> response = ct.initial_response(sys, 40, x0)<br /> <br /> # Plot th3 results<br /> for i in range(response.nstates):<br /> plt.plot(response.time, response.states[i], 'b-')<br /> <br /> # Label the figure<br /> plt.xlabel(&quot;Iteration&quot;)<br /> plt.ylabel(&quot;Agent states $x_i$&quot;)<br /> plt.title(&quot;Consensus convergence&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.24-consensus_dynamics.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.24:_Consensus_protocols_for_sensor_networks&diff=747 Figure 3.24: Consensus protocols for sensor networks 2021-08-30T16:23:47Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=24<br /> |Figure title=Consensus protocols for sensor networks<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.24-consensus.py<br /> }}<br /> [[Image:figure-3.24-consensus_dynamics.png|320px]]<br /> <br /> Figure 3.24: Consensus protocols for sensor networks. (b) A simulation demonstrating the convergence of the consensus protocol (3.35) to the average value of the initial conditions.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.17-consensus.py - consensus protocols<br /> # RMM, 30 Aug 2021<br /> <br /> # Figure 3.24: Consensus protocols for sensor networks. (a) A simple sensor<br /> # net- work with five nodes. In this network, node 1 communicates with node<br /> # 2 and node 2 communicates with nodes 1, 3, 4, 5, etc. (b) A simulation<br /> # demonstrating the convergence of the consensus protocol (3.35) to the<br /> # average value of the initial conditions.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> #<br /> # System dynamcis<br /> #<br /> <br /> # Construct the Laplacian corresponding to our network<br /> L = np.array([<br /> [ 1, -1, 0, 0, 0],<br /> [-1, 4, -1, -1, -1],<br /> [ 0, -1, 2, -1, 0],<br /> [ 0, -1, -1, 2, 0],<br /> [ 0, -1, 0, 0, 1]<br /> ])<br /> <br /> # Now generate the discrete time dynamics matrix<br /> gamma = 0.1<br /> A = np.eye(5) - gamma * L<br /> <br /> # Initial set of measurements for the system<br /> x0 = [10, 15, 25, 35, 40]<br /> <br /> # Create a discrete time system<br /> sys = ct.ss(A, np.zeros(5), np.zeros(5), 0, dt=True)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (b) A simulation demonstrating the convergence of the consensus protocol<br /> # (3.35) to the average value of the initial conditions.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, first column<br /> <br /> # Simulate the system<br /> response = ct.initial_response(sys, 40, x0)<br /> <br /> # Plot th3 results<br /> for i in range(response.nstates):<br /> plt.plot(response.time, response.states[i], 'b-')<br /> <br /> # Label the figure<br /> plt.xlabel(&quot;Iteration&quot;)<br /> plt.ylabel(&quot;Agent states $x_i$&quot;)<br /> plt.title(&quot;Consensus convergence&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.24-consensus_dynamics.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.24-consensus_dynamics.png&diff=746 File:Figure-3.24-consensus dynamics.png 2021-08-30T16:23:12Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.24:_Consensus_protocols_for_sensor_networks&diff=745 Figure 3.24: Consensus protocols for sensor networks 2021-08-30T16:22:51Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=24 |Figure title=Consensus protocols for sensor networks |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=24<br /> |Figure title=Consensus protocols for sensor networks<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.24-consensus.py<br /> }}<br /> [[Image:figure-3.24-consensus_dynamics.png|640px]]<br /> <br /> Figure 3.24: Consensus protocols for sensor networks. (b) A simulation demonstrating the convergence of the consensus protocol (3.35) to the average value of the initial conditions.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.17-consensus.py - consensus protocols<br /> # RMM, 30 Aug 2021<br /> <br /> # Figure 3.24: Consensus protocols for sensor networks. (a) A simple sensor<br /> # net- work with five nodes. In this network, node 1 communicates with node<br /> # 2 and node 2 communicates with nodes 1, 3, 4, 5, etc. (b) A simulation<br /> # demonstrating the convergence of the consensus protocol (3.35) to the<br /> # average value of the initial conditions.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> #<br /> # System dynamcis<br /> #<br /> <br /> # Construct the Laplacian corresponding to our network<br /> L = np.array([<br /> [ 1, -1, 0, 0, 0],<br /> [-1, 4, -1, -1, -1],<br /> [ 0, -1, 2, -1, 0],<br /> [ 0, -1, -1, 2, 0],<br /> [ 0, -1, 0, 0, 1]<br /> ])<br /> <br /> # Now generate the discrete time dynamics matrix<br /> gamma = 0.1<br /> A = np.eye(5) - gamma * L<br /> <br /> # Initial set of measurements for the system<br /> x0 = [10, 15, 25, 35, 40]<br /> <br /> # Create a discrete time system<br /> sys = ct.ss(A, np.zeros(5), np.zeros(5), 0, dt=True)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (b) A simulation demonstrating the convergence of the consensus protocol<br /> # (3.35) to the average value of the initial conditions.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, first column<br /> <br /> # Simulate the system<br /> response = ct.initial_response(sys, 40, x0)<br /> <br /> # Plot th3 results<br /> for i in range(response.nstates):<br /> plt.plot(response.time, response.states[i], 'b-')<br /> <br /> # Label the figure<br /> plt.xlabel(&quot;Iteration&quot;)<br /> plt.ylabel(&quot;Agent states $x_i$&quot;)<br /> plt.title(&quot;Consensus convergence&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.24-consensus_dynamics.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.22-queuing_dynamics.png&diff=744 File:Figure-3.22-queuing dynamics.png 2021-08-30T05:32:25Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.22:_Queuing_dynamics&diff=743 Figure 3.22: Queuing dynamics 2021-08-30T05:32:05Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=22 |Figure title=Queuing dynamics |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.15-queuing_systems....&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=22<br /> |Figure title=Queuing dynamics<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.15-queuing_systems.py<br /> }}<br /> [[Image:figure-3.22-queuing_dynamics.png|640px]]<br /> <br /> '''Figure 3.22:''' Queuing dynamics. (a) The steady-state queue length as a function of &lt;math&gt;\lambda/\mu_\text{max}&lt;/math&gt;. (b) The behavior of the queue length when there is a temporary overload in the system. The solid line shows a realization of an event-based simulation, and the dashed line shows the behavior of the flow model (3.33). The maximum service rate is &lt;math&gt;\mu_{max} = 1&lt;/math&gt;, and the arrival rate starts at &lt;math&gt;\lambda = 0.5&lt;/math&gt;. The arrival rate is increased to &lt;math&gt;\lambda = 4&lt;/math&gt; at time 20, and it returns to &lt;math&gt;\lambda =0.5&lt;/math&gt; at # time 25.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.15-queuing_systems.py - Queuing system modeling<br /> # RMM, 29 Aug 2021<br /> #<br /> # Figure 3.22: Queuing dynamics. (a) The steady-state queue length as a<br /> # function of $\lambda/\mu_{max}$. (b) The behavior of the queue length when<br /> # there is a temporary overload in the system. The solid line shows a<br /> # realization of an event-based simulation, and the dashed line shows the<br /> # behavior of the flow model (3.33). The maximum service rate is $\mu_{max}<br /> # = 1$, and the arrival rate starts at $\lambda = 0.5$. The arrival rate is<br /> # increased to $\lambda = 4$ at time 20, and it returns to $\lambda =0.5$ at<br /> # time 25.<br /> #<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> # Queing parameters <br /> <br /> # Queuing system model (KJA, 2006)<br /> def queuing_model(t, x, u, params={}):<br /> # Define default parameters<br /> mu = params.get('mu', 1)<br /> <br /> # Get the current load<br /> lambda_ = u<br /> <br /> # Return the change in queue size<br /> return np.array(lambda_ - mu * x / (1 + x))<br /> <br /> # Create I/O system representation<br /> queuing_sys = ct.NonlinearIOSystem(<br /> updfcn=queuing_model, inputs=1, outputs=1, states=1)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(3, 2)<br /> <br /> #<br /> # (a) The steady-state queue length as a function of $\lambda/\mu_{max}$.<br /> #<br /> <br /> fig.add_subplot(gs[0, 0]) # first row, first column<br /> <br /> # Steady state queue length<br /> x = np.linspace(0.01, 0.99, 100)<br /> plt.plot(x, x / (1 - x), 'b-')<br /> <br /> # Label the plot<br /> plt.xlabel(r&quot;Service rate excess $\lambda/\mu_{max}$&quot;)<br /> plt.ylabel(r&quot;Queue length $x_{e}$&quot;)<br /> plt.title(&quot;Steady-state queue length&quot;)<br /> <br /> #<br /> # (b) The behavior of the queue length when there is a temporary overload<br /> # in the system. The solid line shows a realization of an event-based<br /> # simulation, and the dashed line shows the behavior of the flow model<br /> # (3.33). The maximum service rate is $\mu_{max} = 1$, and the arrival<br /> # rate starts at $\lambda = 0.5$. The arrival rate is increased to $\lambda<br /> # = 4$ at time 20, and it returns to $\lambda =0.5$ at time 25.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, first column<br /> <br /> # Construct the loading condition<br /> t = np.linspace(0, 80, 100)<br /> <br /> u =np.ones_like(t) * 0.5<br /> u[t &lt;= 25] = 4<br /> u[t &lt; 20] = 0.5<br /> <br /> # Simulate the system dynamics<br /> response = ct.input_output_response(queuing_sys, t, u)<br /> <br /> # Plot the results<br /> plt.plot(response.time, response.outputs, 'b-')<br /> <br /> # Label the plot<br /> plt.xlabel(&quot;Time $t$ [s]&quot;)<br /> plt.ylabel(r&quot;Queue length $x_{e}$&quot;)<br /> plt.title(&quot;Overload condition&quot;)<br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.22-queuing_dynamics.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.12-frequency_response.png&diff=742 File:Figure-3.12-frequency response.png 2021-08-29T16:19:14Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.12:_Frequency_response_computed_by_measuring_the_response_of_individual_sinusoids&diff=741 Figure 3.12: Frequency response computed by measuring the response of individual sinusoids 2021-08-29T16:18:58Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=12 |Figure title=A frequency response (gain only) computed by measuring # the response of individual sinusoids |GitHub URL=htt...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=12<br /> |Figure title=A frequency response (gain only) computed by measuring # the response of individual sinusoids<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.12-frequency_response.py<br /> }}<br /> [[Image:figure-3.12-frequency_response.png|640px]]<br /> <br /> '''Figure 3.12''': A frequency response (gain only) computed by measuring the response of individual sinusoids. The figure on the left shows the response of the system as a function of time to a number of different unit magnitude inputs (at different frequencies). The figure on the right shows this same data in a different way, with the magnitude of the response plotted as a function of the input frequency. The filled circles correspond to the particular frequencies shown in the time responses.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.12-frequency_response.py - frequency response computed by simulation<br /> #<br /> # Figure 3.12: A frequency response (gain only) computed by measuring<br /> # the response of individual sinusoids. The figure on the left shows<br /> # the response of the system as a function of time to a number of<br /> # different unit magnitude inputs (at different frequencies). The<br /> # figure on the right shows this same data in a different way, with<br /> # the magnitude of the response plotted as a function of the input<br /> # frequency. The filled circles correspond to the particular<br /> # frequencies shown in the time responses.<br /> #<br /> <br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> ct.use_fbs_defaults()<br /> <br /> # System definition - third order, state space system<br /> A = [[-0.2, 2, 0], [-0.5, -0.2, 4], [0, 0, -10]]<br /> B = [0, 0, 1]<br /> C = [2.6, 0, 0]<br /> sys = ct.ss(A, B, C, 0) * 1.4 # state space object (with tweaked scale)<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(2, 2)<br /> <br /> #<br /> # (a) The response of the system as a function of time to a number of<br /> # different unit magnitude inputs (at different frequencies). <br /> #<br /> <br /> fig.add_subplot(gs[0, 0]) # first row, first column<br /> <br /> # List of frequencies for the time simulations (and frequency response points)<br /> omega_time = [0.1, 0.4, 1, 3]<br /> mag_time = [] # list to store magnitude of responses<br /> <br /> # Manual computation of the frequency response<br /> for omega in omega_time:<br /> # Compute out the time vector and inputs<br /> t = np.linspace(0, 50, 1000)<br /> u = np.sin(omega * t)<br /> <br /> # Simulate the system<br /> response = ct.forced_response(sys, t, u)<br /> <br /> # Plot the output<br /> plt.plot(response.time, response.outputs, 'b-')<br /> <br /> # Compute the magnitude of the response (avoiding initial transient)<br /> mag_time.append(max(response.outputs[500:]))<br /> <br /> # Add grid lines<br /> plt.xticks([0, 10, 20, 30, 40, 50])<br /> plt.grid(which='major')<br /> <br /> # Label the plot<br /> plt.xlabel(&quot;Time [s]&quot;)<br /> plt.ylabel(&quot;Output, $y$&quot;)<br /> plt.title(&quot;Time domain simulations&quot;)<br /> <br /> #<br /> # (b) The same data in a different way, with the magnitude of the<br /> # response plotted as a function of the input frequency. The filled<br /> # circles correspond to the particular frequencies shown in the time<br /> # responses.<br /> #<br /> <br /> fig.add_subplot(gs[0, 1]) # first row, second column<br /> <br /> # List of frequencies to compute the frequency response<br /> omega_freq = [0.1, 0.2, 0.4, 1, 1.6, 3, 8, 10]<br /> mark_index = [1, 4, 6] # frequencies to mark on the plot<br /> mag_freq = [] # list to store magnitude of responses<br /> <br /> # Manual computation of the frequency response<br /> for omega in omega_freq:<br /> # Compute out the time vector and inputs<br /> t = np.linspace(0, 50, 1000)<br /> u = np.sin(omega * t)<br /> <br /> # Simulate the system<br /> response = ct.forced_response(sys, t, u)<br /> <br /> # Compute the magnitude of the response (avoiding initial transient)<br /> mag_freq.append(max(response.outputs[500:]))<br /> <br /> # Figure out which frequency points to mark<br /> omega_mark = np.array(omega_freq)[mark_index]<br /> mag_mark = np.array(mag_freq)[mark_index]<br /> <br /> # Plot the results<br /> plt.loglog(omega_freq, mag_freq, 'b-')<br /> plt.loglog(omega_mark, mag_mark, 'bo', markerfacecolor='none')<br /> plt.loglog(omega_time, mag_time, 'bo')<br /> <br /> plt.grid(axis='x', which='minor')<br /> plt.grid(axis='y', which='major')<br /> <br /> # Label the plot<br /> plt.xlabel(&quot;Frequency [rad/s]&quot;)<br /> plt.ylabel(&quot;Gain (log scale)&quot;)<br /> plt.title(&quot;Frequency response&quot;)<br /> <br /> plt.savefig(&quot;figure-3.12-frequency_response.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_2.9:_Responses_to_a_unit_step_change_in_the_reference_signal_for_different_values_of_the_design_parameters&diff=740 Figure 2.9: Responses to a unit step change in the reference signal for different values of the design parameters 2021-08-29T05:58:33Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=Feedback Principles<br /> |Figure number=9<br /> |Figure title=Responses to a unit step change in the reference signal for different values of the design parameters<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-2.9-secord_stepresp.py<br /> }}<br /> [[Image:figure-2.9-secord_stepresp.png]]<br /> <br /> '''Figure 2.9:''' Responses to a unit step change in the reference signal for different values of the design parameters &lt;math&gt;\omega_\text{c}&lt;/math&gt; and &lt;math&gt;\zeta_\text{c}&lt;/math&gt;. The left figure shows responses for fixed &lt;math&gt;\zeta_\text{c} = &lt;/math&gt;0.707 and &lt;math&gt;\omega_\text{c} =&lt;/math&gt; 1, 2, and 5. The right figure shows responses for &lt;math&gt;\omega_\text{c} = &lt;/math&gt; 2 and &lt;math&gt;\zeta_\text{c = }&lt;/math&gt; 0.5, 0.707, and 1. The process parameters are &lt;math&gt;a = b = 1&lt;/math&gt;. The initial value of the control signal is &lt;math&gt;k_\text{p}&lt;/math&gt;.<br /> <br /> &lt;nowiki&gt;<br /> # figure-2.9-secord_stepresp.py - step responses for second order systems<br /> # RMM, 21 Jun 2021<br /> #<br /> # Responses to a unit step change in the reference signal for different<br /> # values of the design parameters \omega_c and \zeta_c. The left column<br /> # shows responses for fixed \zeta_c = 0.707 and \omega_c = 1, 2, and 5. The<br /> # right figure column responses for \omega_c = 2 and \zeta_c = 0.5, 0.707,<br /> # and 1. The process parameters are a = b = 1. The initial value of the<br /> # control signal is kp.<br /> #<br /> <br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> # Process model<br /> b = 1; a = 1<br /> P = ct.tf([b], [1, a])<br /> <br /> # Set the simulation time vector<br /> time = np.linspace(0, 6, 100)<br /> <br /> #<br /> # Omega sweep<br /> #<br /> <br /> # Choose gains to use<br /> wc_list = [1, 2, 5]<br /> zc = 0.707<br /> <br /> for wc in wc_list:<br /> kp = (2 * zc * wc - a) / b<br /> ki = wc**2<br /> C = ct.tf([kp, ki], [1, 0])<br /> <br /> Gyr = P*C / (1 + P*C)<br /> Gur = C / (1 + P*C)<br /> <br /> t, y = ct.step_response(Gyr, time)<br /> t, u = ct.step_response(Gur, time)<br /> <br /> if 'w_y_ax' not in locals():<br /> w_y_ax = plt.subplot(3, 2, 1)<br /> plt.ylabel('Output $y$')<br /> plt.title(&quot;Sweep $\omega_c$, $\zeta_c = %g$&quot; % zc)<br /> w_y_ax.plot(t, y)<br /> <br /> if 'w_u_ax' not in locals():<br /> w_u_ax = plt.subplot(3, 2, 3)<br /> plt.ylabel('Input $u$')<br /> plt.xlabel('Normalized time $\omega_c t$')<br /> w_u_ax.plot(t, u, label=&quot;$\omega_c = %g$&quot; % wc)<br /> <br /> # Label the omega sweep curves<br /> w_u_ax.legend(loc=&quot;upper right&quot;)<br /> <br /> #<br /> # Zeta sweep<br /> #<br /> <br /> # Figure out frequency of critical damping<br /> wc = 2<br /> zc_list = [0.5, 0.707, 1]<br /> <br /> # Plot results for different resonate frequencies<br /> for zc in zc_list:<br /> kp = (2 * zc * wc - a) / b<br /> ki = wc**2<br /> C = ct.tf([kp, ki], [1, 0])<br /> <br /> Gyr = P*C / (1 + P*C)<br /> Gur = C / (1 + P*C)<br /> <br /> t, y = ct.step_response(Gyr, time)<br /> t, u = ct.step_response(Gur, time)<br /> <br /> if 'z_y_ax' not in locals():<br /> z_y_ax = plt.subplot(3, 2, 2)<br /> plt.ylabel('Output $y$')<br /> plt.title(&quot;Sweep $\zeta_c$, $\omega_c = %g$&quot; % wc)<br /> z_y_ax.plot(t, y)<br /> <br /> if 'z_u_ax' not in locals():<br /> z_u_ax = plt.subplot(3, 2, 4)<br /> plt.ylabel('Input $u$')<br /> plt.xlabel('Normalized time $\omega_c t$')<br /> z_u_ax.plot(t, u, label=&quot;$\zeta_c = %g$&quot; % zc)<br /> <br /> # Label the zeta sweep curves<br /> z_u_ax.legend(loc=&quot;upper right&quot;)<br /> <br /> # Overalll figure labeling<br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_2.8:_Step_responses_for_a_first-order,_closed_loop_system_with_proportional_and_PI_control&diff=739 Figure 2.8: Step responses for a first-order, closed loop system with proportional and PI control 2021-08-29T05:58:25Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=Feedback Principles<br /> |Figure number=8<br /> |Figure title=Step responses for a first-order, closed loop system with proportional # control and PI control.<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-2.8-PI_step_responses.py<br /> }}<br /> [[Image:figure-2.8-PI_step_response.png]]<br /> <br /> '''Figure 2.8''': Step responses for a first-order, closed loop system with proportional control (a) and PI control (b). The process transfer function is &lt;math&gt;P = 2/(s + 1)&lt;/math&gt;. The controller gains for proportional control are &lt;math&gt;k_\text{p} =&lt;/math&gt; 0, 0.5, 1, and 2. The PI controller is designed using equation (2.28) with &lt;math&gt;\zeta_\text{c} =&lt;/math&gt; 0.707 and &lt;math&gt;\omega_\text{c} =&lt;/math&gt; 0.707, 1, and 2, which gives the controller parameters &lt;math&gt;k_\text{p} =&lt;/math&gt; 0, 0.207, and 0.914 and &lt;math&gt;k_\text{i} =&lt;/math&gt; 0.25, 0.50, and 2.<br /> <br /> &lt;nowiki&gt;<br /> # figure-2.8-PI_step_reesponses.py - step responses for P/PI controllers<br /> # RMM, 21 Jun 2021<br /> #<br /> # Step responses for a first-order, closed loop system with proportional<br /> # control and PI control. The process transfer function is P = 2/(s + 1).<br /> # The controller gains for proportional control are k_p = 0, 0.5, 1, and<br /> # 2. The PI controller is designed using equation (2.28) with zeta_c = 0.707<br /> # and omega_c = 0.707, 1, and 2, which gives the controller parameters k_p =<br /> # 0, 0.207, and 0.914 and k_i = 0.25, 0.50, and 2.<br /> #<br /> <br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> # Process model<br /> b = 2; a = 1<br /> P = ct.tf([b], [1, a])<br /> <br /> # Set the simulation time vector<br /> time = np.linspace(0, 8, 100)<br /> <br /> #<br /> # Proportional control<br /> #<br /> <br /> # Choose gains to use<br /> kp_gains = [0, 0.5, 1, 2]<br /> <br /> for kp in kp_gains:<br /> Gyv = ct.tf([b], [1, a + b*kp])<br /> Guv = ct.tf([-b*kp], [1, a + b*kp], dt=0) # force kp=0 to be cts time<br /> <br /> t, y = ct.step_response(Gyv, time)<br /> t, u = ct.step_response(Guv, time)<br /> <br /> if 'p_y_ax' not in locals():<br /> p_y_ax = plt.subplot(3, 2, 1)<br /> plt.ylabel('Output $y$')<br /> plt.title('Proportional control')<br /> p_y_ax.plot(t, y)<br /> <br /> if 'p_u_ax' not in locals():<br /> p_u_ax = plt.subplot(3, 2, 3)<br /> plt.ylabel('Input $u$')<br /> plt.xlabel('Normalized time $at$')<br /> p_u_ax.plot(t, u, label=&quot;kp = %0.3g&quot; % kp)<br /> <br /> # Label proportional control curves<br /> p_u_ax.legend()<br /> <br /> #<br /> # PI control<br /> #<br /> <br /> # Figure out frequency of critical damping<br /> zeta = 0.707<br /> wc = a / 2 / zeta <br /> <br /> # Plot results for different resonate frequencies<br /> wc_list = [wc, 1, 2]<br /> for wc in wc_list:<br /> kp = (2 * zeta * wc - a) / b<br /> ki = wc**2 / b<br /> <br /> Gyv = ct.tf([b, 0], [1, a + b*kp, b*ki])<br /> Guv = -ct.tf([b*kp, b*ki], [1, a + b*kp, b*ki], dt=0)<br /> <br /> t, y = ct.step_response(Gyv, time)<br /> t, u = ct.step_response(Guv, time)<br /> <br /> if 'pi_y_ax' not in locals():<br /> pi_y_ax = plt.subplot(3, 2, 2)<br /> plt.ylabel('Output $y$')<br /> plt.title('Proportional-integral control')<br /> pi_y_ax.plot(t, y)<br /> <br /> if 'pi_u_ax' not in locals():<br /> pi_u_ax = plt.subplot(3, 2, 4)<br /> plt.ylabel('Input $u$')<br /> plt.xlabel('Normalized time $at$')<br /> pi_u_ax.plot(t, u, label=&quot;wc = %0.3g&quot; % wc)<br /> <br /> # Label PI curves<br /> pi_u_ax.legend()<br /> <br /> # Overalll figure labeling<br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_1.11:_A_feedback_system_for_controlling_the_velocity_of_a_vehicle&diff=738 Figure 1.11: A feedback system for controlling the velocity of a vehicle 2021-08-29T05:57:32Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=Introduction<br /> |Figure number=11<br /> |Figure title=A feedback system for controlling the velocity of a vehicle<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-1.11-cruise_robustness.py<br /> |Requires=cruise.py<br /> }}<br /> [[Image:figure-1.11-cruise_robustness.png]]<br /> <br /> '''Figure 1.11:''' A feedback system for controlling the velocity of a vehicle. In the block diagram on the left, the velocity of the vehicle is measured and compared to the desired velocity within the “Compute” block. Based on the difference in the actual and desired velocities, the throttle (or brake) is used to modify the force applied to the vehicle by the engine, drivetrain, and wheels. The figure on the right shows how the velocity changes when the car travels on a horizontal road and the slope of the road changes to a constant uphill slope. The three different curves correspond to differing masses of the vehicle, between 1200 and 2000 kg, demonstrating that feedback can indeed compensate for the changing slope and that the closed loop system is robust to a large change in the vehicle characteristics.<br /> <br /> &lt;nowiki&gt;<br /> # figure-1.11-cruise_robustness.py - Cruise control w/ range of vehicle masses<br /> # RMM, 20 Jun 2021<br /> # <br /> # This script generates the response of the system to a 4 deg hill with<br /> # different vehicles masses. The figure shows how the velocity changes when<br /> # the car travels on a horizontal road and the slope of the road changes to<br /> # a constant uphill slope. The three different curves correspond to<br /> # differing masses of the vehicle, between 1200 and 2000 kg, demonstrating<br /> # that feedback can indeed compensate for the changing slope and that the<br /> # closed loop system is robust to a large change in the vehicle<br /> # characteristics.<br /> <br /> # Package import<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> import cruise<br /> <br /> # Define the time and input vectors<br /> T = np.linspace(0, 25, 101)<br /> vref = 20 * np.ones(T.shape)<br /> gear = 4 * np.ones(T.shape)<br /> theta0 = np.zeros(T.shape)<br /> <br /> # Now simulate the effect of a hill at t = 5 seconds<br /> theta_hill = np.array([<br /> 0 if t &lt;= 5 else<br /> 4./180. * np.pi * (t-5) if t &lt;= 6 else<br /> 4./180. * np.pi for t in T])<br /> <br /> # Create the plot and add a line at the reference speed<br /> plt.subplot(2, 1, 1)<br /> plt.axis([0, T[-1], 18.75, 20.25])<br /> plt.plot([T, T[-1]], [vref, vref[-1]], 'k-') # reference velocity<br /> plt.plot([5, 5], [18.75, 20.25], 'k:') # disturbance start<br /> <br /> masses = [1200, 1600, 2000]<br /> handles = []<br /> for i, m in enumerate(masses):<br /> # Compute the equilibrium state for the system<br /> X0, U0 = ct.find_eqpt(<br /> cruise.cruise_PI,<br /> [vref, 0],<br /> [vref, gear, theta0], <br /> iu=[1, 2], y0=[vref, 0], iy=, params={'m':m})<br /> <br /> # Simulate the effect of a hill<br /> t, y = ct.input_output_response(<br /> cruise.cruise_PI, T,<br /> [vref, gear, theta_hill],<br /> X0, params={'m':m})<br /> <br /> # Plot the response for this mass<br /> plt.plot(t, y[cruise.cruise_PI.find_output('v')], label='m = %d' % m)<br /> <br /> # Add labels and legend to the plot<br /> plt.xlabel('Time [s]')<br /> plt.ylabel('Velocity [m/s]')<br /> plt.legend()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_1.18:_Air%E2%80%93fuel_controller_based_on_selectors&diff=737 Figure 1.18: Air–fuel controller based on selectors 2021-08-29T05:56:56Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=Introduction<br /> |Figure number=18<br /> |Figure title=Air–fuel controller based on selectors<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-1.18-airfuel_selectors.py<br /> }}<br /> [[Image:figure-1.18-airfuel-blk.png|300px]] &amp;nbsp;<br /> [[Image:figure-1.18-airfuel_selectors.png]]<br /> <br /> '''Figure 1.18:''' Air–fuel controller based on selectors. The left figure shows the system architecture. The letters R and Y in the PI controller denote the input ports for reference and measured signal respectively. The right figure shows a simulation where the power reference r is changed stepwise at t = 1 and t = 15. Notice that the normalized air flow is larger than the normalized fuel flow both for increasing and decreasing reference steps.<br /> <br /> &lt;nowiki&gt;<br /> # figure-1.18-airfuel_selectors.py - Air-fuel control example<br /> # RMM, 20 Jun 2021<br /> #<br /> # Air–fuel controller based on selectors. The right figure shows a<br /> # simulation where the power reference r is changed stepwise at t = 1 and t<br /> # = 15. Notice that the normalized air flow is larger than the normalized<br /> # fuel flow both for increasing and decreasing reference steps.<br /> <br /> # Package import<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> import cruise<br /> <br /> #<br /> # Air and fuel (oil) dynamics and controllers<br /> # <br /> # These dynamics come from Karl Astrom and are embedded in a SIMULINK<br /> # diagram used for the initial part of the book. The basic structure for<br /> # both the air and fuel controllers is a PI controller with output feedback<br /> # for the proportional term and integral feedback on the error. This cuts<br /> # the feedthrough term for the proportional feedback and gives a smoother<br /> # step response (see Figure 11.1b for the basic structure).<br /> #<br /> <br /> # Min selector for oil PI controller input<br /> min_block = ct.NonlinearIOSystem(<br /> updfcn=None, outfcn=lambda t, x, u, params: min(u),<br /> name='min', inputs=['u1', 'u2'], outputs='y')<br /> <br /> # Max selector for air PI controller input<br /> max_block = ct.NonlinearIOSystem(<br /> updfcn=None, outfcn=lambda t, x, u, params: max(u),<br /> name='max', inputs=['u1', 'u2'], outputs='y')<br /> <br /> # Oil and air flow dynamics (from KJA SIMULINK diagram)<br /> Po = ct.tf(, [1, 1])<br /> Pa = ct.tf(, [1, 4])<br /> <br /> # PI controller for oil flow<br /> kpo = 2; kio = 4<br /> Cio = ct.tf([kio], [1, 0])<br /> Cpo = kpo<br /> oil_block = ct.LinearIOSystem(<br /> ct.tf2ss(Po * Cio / (1 + Po * (Cio + Cpo))),<br /> name=&quot;oil&quot;, inputs='r', outputs='y')<br /> <br /> # PI controller for air flow<br /> kpa = 1; kia = 1<br /> Cia = ct.tf([kia], [1, 0])<br /> Cpa = kpa<br /> air_block = ct.LinearIOSystem(<br /> ct.tf2ss(Pa * Cia / (1 + Pa * (Cia + Cpa))),<br /> name=&quot;air&quot;, inputs='r', outputs='y')<br /> <br /> #<br /> # Air-fuel selector dynamics<br /> #<br /> # The selector dynamics are based on the diagram Figure 1.18a, where we have<br /> # already pre-computing the transfer function around the process/controller<br /> # pairs (so the air and oil blocks have input 'R' and output 'Y' from the<br /> # diagram). We use the interconnect function along with named signals to<br /> # set everything up.<br /> #<br /> <br /> airfuel = ct.interconnect(<br /> [min_block, max_block, oil_block, air_block],<br /> connections = (<br /> ['oil.r', 'min.y'],<br /> ['air.r', 'max.y'],<br /> ['min.u2', 'air.y'],<br /> ['max.u1', 'oil.y']),<br /> inplist = [['min.u1', 'max.u2']], inputs='ref',<br /> outlist = ['air.y', 'oil.y'], outputs=['air', 'oil'])<br /> <br /> #<br /> # Input/output response<br /> #<br /> # Finally, we simulate the dynamics with an input singla as showin in Figure<br /> # 1.18b, consisting of a step increase from 0 to 1 at time t = 1 sec and<br /> # then a decrease from 1 to 0.5 at time t = 15 sec.<br /> #<br /> <br /> T = np.linspace(0, 30, 101)<br /> ref = np.array([<br /> 0 if t &lt;= 1 else<br /> 1 if t &lt;= 15 else<br /> 0.5 for t in T])<br /> t, y = ct.input_output_response(airfuel, T, ref)<br /> <br /> # Plot the results<br /> plt.subplot(2, 2, 1)<br /> plt.plot(t, ref, t, y, t, y)<br /> <br /> plt.legend(['ref', 'air', 'fuel'])<br /> plt.xlabel('Time $t$ [sec]')<br /> plt.ylabel('Normalized signals')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Property:Figure_number&diff=736 Property:Figure number 2021-08-29T05:54:54Z <p>Murray: </p> <hr /> <div>This is a property of type [[Has type::Number]].</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.8:_Discrete-time_simulation_of_the_predator%E2%80%93prey_model&diff=735 Figure 3.8: Discrete-time simulation of the predator–prey model 2021-08-29T05:52:48Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=8<br /> |Figure title=Discrete-time simulation of the predator–prey model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.4-predator_prey.py<br /> }}<br /> [[Image:figure-3.8-predator_prey.png|640px]]<br /> <br /> '''Figure 3.8''': Discrete-time simulation of the predator–prey model (3.13). Using the parameters &lt;math&gt;a = c = 0.014&lt;/math&gt;, &lt;math&gt;b_h(u) = 0.6&lt;/math&gt;, and &lt;math&gt;d_l = 0.7 &lt;/math&gt; in equation (3.13), the period and magnitude of the lynx and hare population cycles approximately match the data in Figure 3.7.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.4-predator_prey.py - discrete-time simulation of predator–prey model<br /> # RMM, 15 May 2019<br /> #<br /> # Figure 3.8: Discrete-time simulation of the predator–prey model<br /> # (3.13). Using the parameters a = c = 0.014, bh(u) = 0.6, and dl =<br /> # 0.7 in equation (3.13), the period and magnitude of the lynx and<br /> # hare population cycles approximately match the data in Figure 3.7.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> # Define the dynamics of the predator prey system<br /> def predprey(t, x, u, params):<br /> # Parameter setup<br /> a = params.get('a', 0.014) / 365.<br /> bh0 = params.get('bh0', 0.6) / 365.<br /> c = params.get('c', 0.014) / 365.<br /> dl = params.get('dl', 0.7) / 365.<br /> <br /> # Map the states into local variable names<br /> H = x<br /> L = x<br /> <br /> # Compute the input<br /> bhu = bh0 + u<br /> <br /> # Compute the discrete updates<br /> dH = H + bhu * H - a * L * H<br /> dL = L + c * L * H - dl * L<br /> <br /> return [dH, dL]<br /> <br /> # Create a nonlinear I/O system (dt = days)<br /> io_predprey = ct.NonlinearIOSystem(<br /> predprey, None, inputs=('u'), outputs=('H', 'L'),<br /> states=('H', 'L'), name='predprey', dt=1/365)<br /> <br /> X0 = [10, 10] # Initial H, L<br /> T = np.linspace(1845, 1935, 90*365 + 1) # 90 years<br /> <br /> # Simulate the system<br /> response = ct.input_output_response(io_predprey, T, 0, X0)<br /> t, y = response.time, response.outputs<br /> <br /> # Downsample the responses to individual years<br /> yrs = t[::365]<br /> pop = y[:, ::365]<br /> <br /> # Plot the response<br /> plt.subplot(2, 1, 1) # Set the aspect ration to match the text<br /> <br /> plt.plot(yrs, pop, 'b-o', markersize=3)<br /> plt.plot(yrs, pop, 'r--o', markersize=3)<br /> plt.legend([&quot;Hare&quot;, &quot;Lynx&quot;])<br /> <br /> plt.xlabel(&quot;Year&quot;)<br /> plt.ylabel(&quot;Population&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.4:_Input/output_response_of_a_linear_system&diff=734 Figure 3.4: Input/output response of a linear system 2021-08-29T05:52:39Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=4<br /> |Figure title=Input/output response of a linear system<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.4-io_response.py<br /> }}<br /> [[Image:figure-3.4-io_response.png|640px]]<br /> <br /> '''Figure 3.2''': Input/output response of a linear system. The step response (a) shows the output of the system due to an input that changes from 0 to 1 at time t = 5 s. The frequency response (b) shows the amplitude gain and phase change due to a sinusoidal input at different frequencies.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3-1-io_response.py - input/output response of a linear system<br /> # RMM, 28 Aug 2021<br /> #<br /> # Figure 3.4: Input/output response of a linear system. The step<br /> # response (a) shows the output of the system due to an input that<br /> # changes from 0 to 1 at time t = 5 s. The frequency response (b)<br /> # shows the amplitude gain and phase change due to a sinusoidal input<br /> # at different frequencies.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> ct.use_fbs_defaults() # Use settings to match FBS<br /> <br /> # System definition - third order, state space system<br /> A = [[-0.2, 2, 0], [-0.5, -0.2, 4], [0, 0, -10]]<br /> B = [0, 0, 1]<br /> C = [2.6, 0, 0]<br /> sys = ct.ss(A, B, C, 0) # state space object<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(4, 2)<br /> <br /> #<br /> # (a) Step response showing the output of the system due to an input<br /> # that changes from 0 to 1 at time t = 5 s<br /> #<br /> <br /> fig.add_subplot(gs[0:2, 0]) # first column<br /> <br /> # Create an input signal that is zero until time t = 5<br /> t = np.linspace(0, 30, 100)<br /> u = np.ones_like(t)<br /> u[t &lt; 5] = 0<br /> <br /> # Compute the response<br /> response = ct.forced_response(sys, t, u)<br /> y = response.outputs<br /> <br /> # Plot the response<br /> plt.plot(t, u, 'b--', label=&quot;Input&quot;)<br /> plt.plot(t, y, 'r-', label=&quot;Output&quot;)<br /> plt.xlabel(&quot;Time (sec)&quot;)<br /> plt.ylabel(&quot;Input, output&quot;)<br /> plt.title(&quot;Step response&quot;)<br /> plt.legend()<br /> <br /> #<br /> # (b) Frequency response showing the amplitude gain and phase change<br /> # due to a sinusoidal input at different frequencies<br /> #<br /> <br /> # Set up the axes for plotting (labels are recognized by bode_plot())<br /> mag = fig.add_subplot(gs[0, 1], label='control-bode-magnitude')<br /> phase = fig.add_subplot(gs[1, 1], label='control-bode-phase')<br /> <br /> # Generate the Bode plot<br /> ct.bode_plot(sys)<br /> <br /> # Adjust the appearance to match the book<br /> mag.xaxis.set_ticklabels([])<br /> mag.set_title(&quot;Frequency response&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.2:_Illustration_of_a_state_model&diff=733 Figure 3.2: Illustration of a state model 2021-08-29T05:52:33Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=2<br /> |Figure title=Illustration of a state model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-state_model.py<br /> }}<br /> [[Image:figure-3.2-state_model.png|640px]]<br /> <br /> '''Figure 3.2''': Illustration of a state model. A state model gives the rate of change of the state as a function of the state. The plot on the left shows the evolution of the state as a function of time. The plot on the right, called a phase portrait, shows the evolution of the states relative to each other, with the velocity of the state denoted by arrows.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.2-state_mode.py - illustration of a state model<br /> # RMM, 2 Jul 2021<br /> #<br /> # Figure 3.2: Illustration of a state model. A state model gives the rate of<br /> # change of the state as a function of the state. The plot on the left shows<br /> # the evolution of the state as a function of time. The plot on the right,<br /> # called a phase portrait, shows the evolution of the states relative to<br /> # each other, with the velocity of the state denoted by arrows.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> #<br /> # Spring mass system with nonlinear dampling<br /> #<br /> # This function gives the dynamics for a dampled oscillator with nonlinear<br /> # damping. The states of the system are<br /> #<br /> # x position<br /> # x velocity<br /> #<br /> # The nonlinear damping is implemented as a change in the linear damping<br /> # coefficient at a small velocity. This is intended to roughly correspond <br /> # to some sort of stiction (and give an interesting phase portrait). The <br /> # default parameters for the system are given by<br /> #<br /> # m = 1 mass, kg<br /> # k = 1 spring constant, N/m<br /> # b1 = 1 damping constant near origin, N-sec/m<br /> # b2 = 0.01 damping constant away from origin, N-sec/m<br /> # dth = 0.5 threshold for switching between damping<br /> #<br /> # This corresponds to a fairly lightly damped oscillator away from the origin.<br /> <br /> def nlspringmass(x, t, u=0, m=1, k=1, b1=2, b2=0.01, dth=0.2):<br /> # Compute the friction force<br /> if abs(x) &lt; dth:<br /> Fb = b1 * x;<br /> elif x &lt; 0:<br /> Fb = -b1 * dth \<br /> + b2 * (x + dth);<br /> else:<br /> Fb = b1 * dth \<br /> + b2 * (x - dth);<br /> <br /> # Return the time derivative of the state<br /> return np.array([x, -k/m * x - Fb/m])<br /> <br /> #<br /> # (a) Simulation of the nonlinear spring mass system<br /> #<br /> plt.subplot(2, 2, 1)<br /> <br /> t = np.linspace(0, 16, 100)<br /> y = sp.integrate.odeint(nlspringmass, [2, 0], t)<br /> <br /> plt.plot(t, y[:, 0], '-', t, y[:, 1], '--')<br /> plt.xlabel('Time $t$ [s]')<br /> plt.ylabel('Position $q$ [m], velocity $\dot q$̇ [m/s]')<br /> plt.title('Time plot')<br /> plt.legend(['Position $q$', 'Velocity $v$'])<br /> <br /> #<br /> # (b) Generate a phase plot for the damped oscillator<br /> #<br /> plt.subplot(2, 2, 2)<br /> <br /> ct.phase_plot(<br /> nlspringmass, # dynamics<br /> (-1, 1, 8), (-1, 1, 8), # X, Y range, npoints<br /> scale=0.2,<br /> X0=[[-1, 0.4], [0.1, 1], [1, -0.4], [-0.1, -1]])<br /> <br /> plt.xlabel('Position $q$ [m]')<br /> plt.ylabel('Velocity $\dot q$ [m/s]')<br /> plt.title('Phase portrait')<br /> plt.axis([-1, 1, -1, 1])<br /> <br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.11:_Simulation_of_the_forced_spring%E2%80%93mass_system_with_different_simulation_time_constants&diff=732 Figure 3.11: Simulation of the forced spring–mass system with different simulation time constants 2021-08-29T05:52:23Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=11<br /> |Figure title=Simulation of the forced spring–mass system with different simulation time constants<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.11-spring_mass_simulation.py<br /> }}<br /> [[image:figure-3.11-spring_mass_simulation.png|640px]]<br /> <br /> '''Figure 3.11''': Simulation of the forced spring–mass system with different simulation time constants. The solid line represents the analytical solution. The dashed lines represent the approximate solution via the method of Euler integration, using decreasing step sizes.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.11-spring_mass_simulation.py - forced spring–mass simulation approx<br /> # RMM, 28 Aug 2021<br /> #<br /> # Figure 3.11: Simulation of the forced spring–mass system with<br /> # different simulation time constants. The solid line represents the<br /> # analytical solution. The dashed lines represent the approximate<br /> # solution via the method of Euler integration, using decreasing step<br /> # sizes.<br /> #<br /> <br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> ct.use_fbs_defaults()<br /> <br /> # Parameters defining the system<br /> m = 250 # system mass<br /> k = 40 # spring constant<br /> b = 60 # damping constant<br /> <br /> # System matrices<br /> A = [[0, 1], [-k/m, -b/m]]<br /> B = [0, 1/m]<br /> C = [1, 0]<br /> sys = ct.ss(A, B, C, 0)<br /> <br /> #<br /> # Discrete time simulation<br /> #<br /> # This section explores what happens when we discretize the ODE<br /> # and convert it to a discrete time simulation.<br /> #<br /> Af = 20 # forcing amplitude<br /> omega = 0.5 # forcing frequency<br /> <br /> # Sinusoidal forcing function<br /> t = np.linspace(0, 100, 1000)<br /> u = Af * np.sin(omega * t)<br /> <br /> # Simulate the system using standard MATLAB routines<br /> response = ct.forced_response(sys, t, u)<br /> ts, ys = response.time, response.outputs<br /> <br /> #<br /> # Now generate some simulations manually<br /> #<br /> <br /> # Time increments for discrete approximations<br /> hvec = [1, 0.5, 0.1] # h must be a multiple of 0.1<br /> max_len = int(t[-1] / min(hvec)) # maximum number of time steps<br /> <br /> # Create arrays for storing results<br /> td = np.zeros((len(hvec), max_len)) # discrete time instants<br /> yd = np.zeros((len(hvec), max_len)) # output at discrete time instants<br /> <br /> # Discrete time simulations<br /> maxi = [] # list to store maximum index<br /> for iter, h in enumerate(hvec):<br /> maxi.append(round(t[-1] / h)) # save maximum index for this h<br /> x = np.zeros((2, maxi[-1] + 1)) # create an array to store the state<br /> <br /> # Compute the discrete time Euler approximation of the dynamics<br /> for i in range(maxi[-1]):<br /> offset = int(h/0.1 * i) # input offset<br /> x[:, i+1] = x[:, i] + h * (sys.A @ x[:, i] + (sys.B * u[offset])[:, 0])<br /> td[iter, i] = (i-1) * h<br /> yd[iter, i] = sys.C @ x[:, i]<br /> <br /> # Plot the results<br /> plt.subplot(2, 1, 1)<br /> <br /> simh = plt.plot(<br /> td[0, 0:maxi], yd[0, 0:maxi], 'g+--',<br /> td[1, 0:maxi], yd[1, 0:maxi], 'ro--',<br /> td[2, 0:maxi], yd[2, 0:maxi], 'b--',<br /> markersize=4, linewidth=1<br /> )<br /> analh = plt.plot(ts, ys, 'k-', linewidth=1)<br /> <br /> plt.xlabel(&quot;Time [s]&quot;)<br /> plt.ylabel(&quot;Position $q$ [m]&quot;)<br /> plt.axis([0, 50, -2, 2])<br /> plt.legend([&quot;$h = %g$&quot; % h for h in hvec] + [&quot;analytical&quot;]), <br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.11-spring_mass_simulation.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Template:Chapter_footer&diff=731 Template:Chapter footer 2021-08-29T05:51:51Z <p>Murray: /* Python Code */</p> <hr /> <div>&lt;br&gt;<br /> {| width=100% border=1<br /> |- valign=top style=&quot;padding-top: 0em&quot;<br /> | width=50% style=&quot;padding-left: 0.5em&quot; |<br /> === Additional Exercises ===<br /> The following exercises cover some of the topics introduced in this chapter. Exercises marked with a * appear in the printed text.<br /> {{#ask: [[Category:Exercises]] |topic={{PAGENAME}} |format=ol }}<br /> <br /> === Frequently Asked Questions ===<br /> {{#ask: [[Category:Questions]] | topic={{PAGENAME}} | format=ol}}<br /> <br /> === Errata ===<br /> {{#ask: [[Category:FAQ]] | topic={{PAGENAME}} | format=ol}}<br /> &lt;!-- * {{submitbug}} --&gt;<br /> <br /> | width=50% style=&quot;padding-left: 0.5em&quot; |<br /> === Python Code ===<br /> The following Python scripts are available for producing figures that appear in this chapter.<br /> <br /> {{#ask: [[Category:Figures]] [[Chapter::{{PAGENAME}}]] | format=ul | sort=Figure number}}<br /> <br /> See the [[software|software page]] for more information on how to run these scripts.<br /> <br /> === Additional Information ===<br /> {{{Additional information|}}}<br /> |}</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.11-spring_mass_simulation.png&diff=730 File:Figure-3.11-spring mass simulation.png 2021-08-29T05:45:18Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.11:_Simulation_of_the_forced_spring%E2%80%93mass_system_with_different_simulation_time_constants&diff=729 Figure 3.11: Simulation of the forced spring–mass system with different simulation time constants 2021-08-29T05:43:07Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=3.11 |Figure title=Simulation of the forced spring–mass system with different simulation time constants |GitHub URL=https://...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.11<br /> |Figure title=Simulation of the forced spring–mass system with different simulation time constants<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.11-spring_mass_simulation.py<br /> }}<br /> [[image:figure-3.11-spring_mass_simulation.png|640px]]<br /> <br /> '''Figure 3.11''': Simulation of the forced spring–mass system with different simulation time constants. The solid line represents the analytical solution. The dashed lines represent the approximate solution via the method of Euler integration, using decreasing step sizes.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.11-spring_mass_simulation.py - forced spring–mass simulation approx<br /> # RMM, 28 Aug 2021<br /> #<br /> # Figure 3.11: Simulation of the forced spring–mass system with<br /> # different simulation time constants. The solid line represents the<br /> # analytical solution. The dashed lines represent the approximate<br /> # solution via the method of Euler integration, using decreasing step<br /> # sizes.<br /> #<br /> <br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> ct.use_fbs_defaults()<br /> <br /> # Parameters defining the system<br /> m = 250 # system mass<br /> k = 40 # spring constant<br /> b = 60 # damping constant<br /> <br /> # System matrices<br /> A = [[0, 1], [-k/m, -b/m]]<br /> B = [0, 1/m]<br /> C = [1, 0]<br /> sys = ct.ss(A, B, C, 0)<br /> <br /> #<br /> # Discrete time simulation<br /> #<br /> # This section explores what happens when we discretize the ODE<br /> # and convert it to a discrete time simulation.<br /> #<br /> Af = 20 # forcing amplitude<br /> omega = 0.5 # forcing frequency<br /> <br /> # Sinusoidal forcing function<br /> t = np.linspace(0, 100, 1000)<br /> u = Af * np.sin(omega * t)<br /> <br /> # Simulate the system using standard MATLAB routines<br /> response = ct.forced_response(sys, t, u)<br /> ts, ys = response.time, response.outputs<br /> <br /> #<br /> # Now generate some simulations manually<br /> #<br /> <br /> # Time increments for discrete approximations<br /> hvec = [1, 0.5, 0.1] # h must be a multiple of 0.1<br /> max_len = int(t[-1] / min(hvec)) # maximum number of time steps<br /> <br /> # Create arrays for storing results<br /> td = np.zeros((len(hvec), max_len)) # discrete time instants<br /> yd = np.zeros((len(hvec), max_len)) # output at discrete time instants<br /> <br /> # Discrete time simulations<br /> maxi = [] # list to store maximum index<br /> for iter, h in enumerate(hvec):<br /> maxi.append(round(t[-1] / h)) # save maximum index for this h<br /> x = np.zeros((2, maxi[-1] + 1)) # create an array to store the state<br /> <br /> # Compute the discrete time Euler approximation of the dynamics<br /> for i in range(maxi[-1]):<br /> offset = int(h/0.1 * i) # input offset<br /> x[:, i+1] = x[:, i] + h * (sys.A @ x[:, i] + (sys.B * u[offset])[:, 0])<br /> td[iter, i] = (i-1) * h<br /> yd[iter, i] = sys.C @ x[:, i]<br /> <br /> # Plot the results<br /> plt.subplot(2, 1, 1)<br /> <br /> simh = plt.plot(<br /> td[0, 0:maxi], yd[0, 0:maxi], 'g+--',<br /> td[1, 0:maxi], yd[1, 0:maxi], 'ro--',<br /> td[2, 0:maxi], yd[2, 0:maxi], 'b--',<br /> markersize=4, linewidth=1<br /> )<br /> analh = plt.plot(ts, ys, 'k-', linewidth=1)<br /> <br /> plt.xlabel(&quot;Time [s]&quot;)<br /> plt.ylabel(&quot;Position $q$ [m]&quot;)<br /> plt.axis([0, 50, -2, 2])<br /> plt.legend([&quot;$h = %g$&quot; % h for h in hvec] + [&quot;analytical&quot;]), <br /> <br /> # Save the figure<br /> plt.savefig(&quot;figure-3.11-spring_mass_simulation.png&quot;, bbox_inches='tight')<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.8:_Discrete-time_simulation_of_the_predator%E2%80%93prey_model&diff=728 Figure 3.8: Discrete-time simulation of the predator–prey model 2021-08-29T05:40:02Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.8<br /> |Figure title=Discrete-time simulation of the predator–prey model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/example-3.4-predator_prey.py<br /> }}<br /> [[Image:figure-3.8-predator_prey.png|640px]]<br /> <br /> '''Figure 3.8''': Discrete-time simulation of the predator–prey model (3.13). Using the parameters &lt;math&gt;a = c = 0.014&lt;/math&gt;, &lt;math&gt;b_h(u) = 0.6&lt;/math&gt;, and &lt;math&gt;d_l = 0.7 &lt;/math&gt; in equation (3.13), the period and magnitude of the lynx and hare population cycles approximately match the data in Figure 3.7.<br /> <br /> &lt;nowiki&gt;<br /> # example-3.4-predator_prey.py - discrete-time simulation of predator–prey model<br /> # RMM, 15 May 2019<br /> #<br /> # Figure 3.8: Discrete-time simulation of the predator–prey model<br /> # (3.13). Using the parameters a = c = 0.014, bh(u) = 0.6, and dl =<br /> # 0.7 in equation (3.13), the period and magnitude of the lynx and<br /> # hare population cycles approximately match the data in Figure 3.7.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> # Define the dynamics of the predator prey system<br /> def predprey(t, x, u, params):<br /> # Parameter setup<br /> a = params.get('a', 0.014) / 365.<br /> bh0 = params.get('bh0', 0.6) / 365.<br /> c = params.get('c', 0.014) / 365.<br /> dl = params.get('dl', 0.7) / 365.<br /> <br /> # Map the states into local variable names<br /> H = x<br /> L = x<br /> <br /> # Compute the input<br /> bhu = bh0 + u<br /> <br /> # Compute the discrete updates<br /> dH = H + bhu * H - a * L * H<br /> dL = L + c * L * H - dl * L<br /> <br /> return [dH, dL]<br /> <br /> # Create a nonlinear I/O system (dt = days)<br /> io_predprey = ct.NonlinearIOSystem(<br /> predprey, None, inputs=('u'), outputs=('H', 'L'),<br /> states=('H', 'L'), name='predprey', dt=1/365)<br /> <br /> X0 = [10, 10] # Initial H, L<br /> T = np.linspace(1845, 1935, 90*365 + 1) # 90 years<br /> <br /> # Simulate the system<br /> response = ct.input_output_response(io_predprey, T, 0, X0)<br /> t, y = response.time, response.outputs<br /> <br /> # Downsample the responses to individual years<br /> yrs = t[::365]<br /> pop = y[:, ::365]<br /> <br /> # Plot the response<br /> plt.subplot(2, 1, 1) # Set the aspect ration to match the text<br /> <br /> plt.plot(yrs, pop, 'b-o', markersize=3)<br /> plt.plot(yrs, pop, 'r--o', markersize=3)<br /> plt.legend([&quot;Hare&quot;, &quot;Lynx&quot;])<br /> <br /> plt.xlabel(&quot;Year&quot;)<br /> plt.ylabel(&quot;Population&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.8:_Discrete-time_simulation_of_the_predator%E2%80%93prey_model&diff=727 Figure 3.8: Discrete-time simulation of the predator–prey model 2021-08-29T02:14:55Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.8<br /> |Figure title=Discrete-time simulation of the predator–prey model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.8-predator_prey.py<br /> }}<br /> [[Image:figure-3.8-predator_prey.png|640px]]<br /> <br /> '''Figure 3.8''': Discrete-time simulation of the predator–prey model (3.13). Using the parameters &lt;math&gt;a = c = 0.014&lt;/math&gt;, &lt;math&gt;b_h(u) = 0.6&lt;/math&gt;, and &lt;math&gt;d_l = 0.7 &lt;/math&gt; in equation (3.13), the period and magnitude of the lynx and hare population cycles approximately match the data in Figure 3.7.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.8-predator_prey.py - discrete-time simulation of predator–prey model<br /> # RMM, 15 May 20219<br /> #<br /> # Figure 3.8: Discrete-time simulation of the predator–prey model<br /> # (3.13). Using the parameters a = c = 0.014, bh(u) = 0.6, and dl =<br /> # 0.7 in equation (3.13), the period and magnitude of the lynx and<br /> # hare population cycles approximately match the data in Figure 3.7.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> # Define the dynamics of the predator prey system<br /> def predprey(t, x, u, params):<br /> # Parameter setup<br /> a = params.get('a', 0.014) / 365.<br /> bh0 = params.get('bh0', 0.6) / 365.<br /> c = params.get('c', 0.014) / 365.<br /> dl = params.get('dl', 0.7) / 365.<br /> <br /> # Map the states into local variable names<br /> H = x<br /> L = x<br /> <br /> # Compute the input<br /> bhu = bh0 + u<br /> <br /> # Compute the discrete updates<br /> dH = H + bhu * H - a * L * H<br /> dL = L + c * L * H - dl * L<br /> <br /> return [dH, dL]<br /> <br /> # Create a nonlinear I/O system (dt = days)<br /> io_predprey = ct.NonlinearIOSystem(<br /> predprey, None, inputs=('u'), outputs=('H', 'L'),<br /> states=('H', 'L'), name='predprey', dt=1/365)<br /> <br /> X0 = [10, 10] # Initial H, L<br /> T = np.linspace(1845, 1935, 90*365 + 1) # 90 years<br /> <br /> # Simulate the system<br /> response = ct.input_output_response(io_predprey, T, 0, X0)<br /> t, y = response.time, response.outputs<br /> <br /> # Downsample the responses to individual years<br /> yrs = t[::365]<br /> pop = y[:, ::365]<br /> <br /> # Plot the response<br /> plt.subplot(2, 1, 1) # Set the aspect ration to match the text<br /> <br /> plt.plot(yrs, pop, 'b-o', markersize=3)<br /> plt.plot(yrs, pop, 'r--o', markersize=3)<br /> plt.legend([&quot;Hare&quot;, &quot;Lynx&quot;])<br /> <br /> plt.xlabel(&quot;Year&quot;)<br /> plt.ylabel(&quot;Population&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.8-predator_prey.png&diff=726 File:Figure-3.8-predator prey.png 2021-08-29T02:14:34Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.8:_Discrete-time_simulation_of_the_predator%E2%80%93prey_model&diff=725 Figure 3.8: Discrete-time simulation of the predator–prey model 2021-08-29T02:13:25Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=3.8 |Figure title=Discrete-time simulation of the predator–prey model |GitHub URL=https://github.com/murrayrm/fbs2e-python/b...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.8<br /> |Figure title=Discrete-time simulation of the predator–prey model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.8-predator_prey.py<br /> }}<br /> [[Image:figure-3.8-predator_prey.png|640px]]<br /> <br /> '''Figure 3.8''': Discrete-time simulation of the predator–prey model (3.13). Using the parameters &lt;math&gt;a = c = 0.014&lt;/math&gt;, &lt;math&gt;b_h(u) = 0.6&lt;/math&gt;, and &lt;math&gt;d_l = 0.7 &lt;/math&gt; in equation (3.13), the period and magnitude of the lynx and hare population cycles approximately match the data in Figure 3.7.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.8-predator_prey.py - discrete-time simulation of predator–prey model<br /> # RMM, 15 May 20219<br /> #<br /> # Figure 3.8: Discrete-time simulation of the predator–prey model<br /> # (3.13). Using the parameters a = c = 0.014, bh(u) = 0.6, and dl =<br /> # 0.7 in equation (3.13), the period and magnitude of the lynx and<br /> # hare population cycles approximately match the data in Figure 3.7.<br /> <br /> import control as ct<br /> import numpy as np<br /> import matplotlib.pyplot as plt<br /> <br /> # Define the dynamics of the predator prey system<br /> def predprey(t, x, u, params):<br /> # Parameter setup<br /> a = params.get('a', 0.014) / 365.<br /> bh0 = params.get('bh0', 0.6) / 365.<br /> c = params.get('c', 0.014) / 365.<br /> dl = params.get('dl', 0.7) / 365.<br /> <br /> # Map the states into local variable names<br /> H = x<br /> L = x<br /> <br /> # Compute the input<br /> bhu = bh0 + u<br /> <br /> # Compute the discrete updates<br /> dH = H + bhu * H - a * L * H<br /> dL = L + c * L * H - dl * L<br /> <br /> return [dH, dL]<br /> <br /> # Create a nonlinear I/O system (dt = days)<br /> io_predprey = ct.NonlinearIOSystem(<br /> predprey, None, inputs=('u'), outputs=('H', 'L'),<br /> states=('H', 'L'), name='predprey', dt=1/365)<br /> <br /> X0 = [10, 10] # Initial H, L<br /> T = np.linspace(1845, 1935, 90*365 + 1) # 90 years<br /> <br /> # Simulate the system<br /> response = ct.input_output_response(io_predprey, T, 0, X0)<br /> t, y = response.time, response.outputs<br /> <br /> # Downsample the responses to individual years<br /> yrs = t[::365]<br /> pop = y[:, ::365]<br /> <br /> # Plot the response<br /> plt.subplot(2, 1, 1) # Set the aspect ration to match the text<br /> <br /> plt.plot(yrs, pop, 'b-o', markersize=3)<br /> plt.plot(yrs, pop, 'r--o', markersize=3)<br /> plt.legend([&quot;Hare&quot;, &quot;Lynx&quot;])<br /> <br /> plt.xlabel(&quot;Year&quot;)<br /> plt.ylabel(&quot;Population&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.4-io_response.png&diff=724 File:Figure-3.4-io response.png 2021-08-29T01:01:51Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.4:_Input/output_response_of_a_linear_system&diff=723 Figure 3.4: Input/output response of a linear system 2021-08-29T01:01:37Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=3.4 |Figure title=Input/output response of a linear system |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figu...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.4<br /> |Figure title=Input/output response of a linear system<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.4-io_response.py<br /> }}<br /> [[Image:figure-3.4-io_response.png|640px]]<br /> <br /> '''Figure 3.2''': Input/output response of a linear system. The step response (a) shows the output of the system due to an input that changes from 0 to 1 at time t = 5 s. The frequency response (b) shows the amplitude gain and phase change due to a sinusoidal input at different frequencies.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3-1-io_response.py - input/output response of a linear system<br /> # RMM, 28 Aug 2021<br /> #<br /> # Figure 3.4: Input/output response of a linear system. The step<br /> # response (a) shows the output of the system due to an input that<br /> # changes from 0 to 1 at time t = 5 s. The frequency response (b)<br /> # shows the amplitude gain and phase change due to a sinusoidal input<br /> # at different frequencies.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> ct.use_fbs_defaults() # Use settings to match FBS<br /> <br /> # System definition - third order, state space system<br /> A = [[-0.2, 2, 0], [-0.5, -0.2, 4], [0, 0, -10]]<br /> B = [0, 0, 1]<br /> C = [2.6, 0, 0]<br /> sys = ct.ss(A, B, C, 0) # state space object<br /> <br /> # Set up the plotting grid to match the layout in the book<br /> fig = plt.figure(constrained_layout=True)<br /> gs = fig.add_gridspec(4, 2)<br /> <br /> #<br /> # (a) Step response showing the output of the system due to an input<br /> # that changes from 0 to 1 at time t = 5 s<br /> #<br /> <br /> fig.add_subplot(gs[0:2, 0]) # first column<br /> <br /> # Create an input signal that is zero until time t = 5<br /> t = np.linspace(0, 30, 100)<br /> u = np.ones_like(t)<br /> u[t &lt; 5] = 0<br /> <br /> # Compute the response<br /> response = ct.forced_response(sys, t, u)<br /> y = response.outputs<br /> <br /> # Plot the response<br /> plt.plot(t, u, 'b--', label=&quot;Input&quot;)<br /> plt.plot(t, y, 'r-', label=&quot;Output&quot;)<br /> plt.xlabel(&quot;Time (sec)&quot;)<br /> plt.ylabel(&quot;Input, output&quot;)<br /> plt.title(&quot;Step response&quot;)<br /> plt.legend()<br /> <br /> #<br /> # (b) Frequency response showing the amplitude gain and phase change<br /> # due to a sinusoidal input at different frequencies<br /> #<br /> <br /> # Set up the axes for plotting (labels are recognized by bode_plot())<br /> mag = fig.add_subplot(gs[0, 1], label='control-bode-magnitude')<br /> phase = fig.add_subplot(gs[1, 1], label='control-bode-phase')<br /> <br /> # Generate the Bode plot<br /> ct.bode_plot(sys)<br /> <br /> # Adjust the appearance to match the book<br /> mag.xaxis.set_ticklabels([])<br /> mag.set_title(&quot;Frequency response&quot;)<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.2:_Illustration_of_a_state_model&diff=722 Figure 3.2: Illustration of a state model 2021-08-29T00:57:22Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.2<br /> |Figure title=Illustration of a state model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-state_model.py<br /> }}<br /> [[Image:figure-3.2-state_model.png|640px]]<br /> <br /> '''Figure 3.2''': Illustration of a state model. A state model gives the rate of change of the state as a function of the state. The plot on the left shows the evolution of the state as a function of time. The plot on the right, called a phase portrait, shows the evolution of the states relative to each other, with the velocity of the state denoted by arrows.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.2-state_mode.py - illustration of a state model<br /> # RMM, 2 Jul 2021<br /> #<br /> # Figure 3.2: Illustration of a state model. A state model gives the rate of<br /> # change of the state as a function of the state. The plot on the left shows<br /> # the evolution of the state as a function of time. The plot on the right,<br /> # called a phase portrait, shows the evolution of the states relative to<br /> # each other, with the velocity of the state denoted by arrows.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> #<br /> # Spring mass system with nonlinear dampling<br /> #<br /> # This function gives the dynamics for a dampled oscillator with nonlinear<br /> # damping. The states of the system are<br /> #<br /> # x position<br /> # x velocity<br /> #<br /> # The nonlinear damping is implemented as a change in the linear damping<br /> # coefficient at a small velocity. This is intended to roughly correspond <br /> # to some sort of stiction (and give an interesting phase portrait). The <br /> # default parameters for the system are given by<br /> #<br /> # m = 1 mass, kg<br /> # k = 1 spring constant, N/m<br /> # b1 = 1 damping constant near origin, N-sec/m<br /> # b2 = 0.01 damping constant away from origin, N-sec/m<br /> # dth = 0.5 threshold for switching between damping<br /> #<br /> # This corresponds to a fairly lightly damped oscillator away from the origin.<br /> <br /> def nlspringmass(x, t, u=0, m=1, k=1, b1=2, b2=0.01, dth=0.2):<br /> # Compute the friction force<br /> if abs(x) &lt; dth:<br /> Fb = b1 * x;<br /> elif x &lt; 0:<br /> Fb = -b1 * dth \<br /> + b2 * (x + dth);<br /> else:<br /> Fb = b1 * dth \<br /> + b2 * (x - dth);<br /> <br /> # Return the time derivative of the state<br /> return np.array([x, -k/m * x - Fb/m])<br /> <br /> #<br /> # (a) Simulation of the nonlinear spring mass system<br /> #<br /> plt.subplot(2, 2, 1)<br /> <br /> t = np.linspace(0, 16, 100)<br /> y = sp.integrate.odeint(nlspringmass, [2, 0], t)<br /> <br /> plt.plot(t, y[:, 0], '-', t, y[:, 1], '--')<br /> plt.xlabel('Time $t$ [s]')<br /> plt.ylabel('Position $q$ [m], velocity $\dot q$̇ [m/s]')<br /> plt.title('Time plot')<br /> plt.legend(['Position $q$', 'Velocity $v$'])<br /> <br /> #<br /> # (b) Generate a phase plot for the damped oscillator<br /> #<br /> plt.subplot(2, 2, 2)<br /> <br /> ct.phase_plot(<br /> nlspringmass, # dynamics<br /> (-1, 1, 8), (-1, 1, 8), # X, Y range, npoints<br /> scale=0.2,<br /> X0=[[-1, 0.4], [0.1, 1], [1, -0.4], [-0.1, -1]])<br /> <br /> plt.xlabel('Position $q$ [m]')<br /> plt.ylabel('Velocity $\dot q$ [m/s]')<br /> plt.title('Phase portrait')<br /> plt.axis([-1, 1, -1, 1])<br /> <br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.2:_Illustration_of_a_state_model&diff=721 Figure 3.2: Illustration of a state model 2021-08-29T00:57:10Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.2<br /> |Figure title=Illustration of a state model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-state_model.py<br /> }}<br /> [[Image:figure-3.2-state_model.png|480px]]<br /> <br /> '''Figure 3.2''': Illustration of a state model. A state model gives the rate of change of the state as a function of the state. The plot on the left shows the evolution of the state as a function of time. The plot on the right, called a phase portrait, shows the evolution of the states relative to each other, with the velocity of the state denoted by arrows.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.2-state_mode.py - illustration of a state model<br /> # RMM, 2 Jul 2021<br /> #<br /> # Figure 3.2: Illustration of a state model. A state model gives the rate of<br /> # change of the state as a function of the state. The plot on the left shows<br /> # the evolution of the state as a function of time. The plot on the right,<br /> # called a phase portrait, shows the evolution of the states relative to<br /> # each other, with the velocity of the state denoted by arrows.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> #<br /> # Spring mass system with nonlinear dampling<br /> #<br /> # This function gives the dynamics for a dampled oscillator with nonlinear<br /> # damping. The states of the system are<br /> #<br /> # x position<br /> # x velocity<br /> #<br /> # The nonlinear damping is implemented as a change in the linear damping<br /> # coefficient at a small velocity. This is intended to roughly correspond <br /> # to some sort of stiction (and give an interesting phase portrait). The <br /> # default parameters for the system are given by<br /> #<br /> # m = 1 mass, kg<br /> # k = 1 spring constant, N/m<br /> # b1 = 1 damping constant near origin, N-sec/m<br /> # b2 = 0.01 damping constant away from origin, N-sec/m<br /> # dth = 0.5 threshold for switching between damping<br /> #<br /> # This corresponds to a fairly lightly damped oscillator away from the origin.<br /> <br /> def nlspringmass(x, t, u=0, m=1, k=1, b1=2, b2=0.01, dth=0.2):<br /> # Compute the friction force<br /> if abs(x) &lt; dth:<br /> Fb = b1 * x;<br /> elif x &lt; 0:<br /> Fb = -b1 * dth \<br /> + b2 * (x + dth);<br /> else:<br /> Fb = b1 * dth \<br /> + b2 * (x - dth);<br /> <br /> # Return the time derivative of the state<br /> return np.array([x, -k/m * x - Fb/m])<br /> <br /> #<br /> # (a) Simulation of the nonlinear spring mass system<br /> #<br /> plt.subplot(2, 2, 1)<br /> <br /> t = np.linspace(0, 16, 100)<br /> y = sp.integrate.odeint(nlspringmass, [2, 0], t)<br /> <br /> plt.plot(t, y[:, 0], '-', t, y[:, 1], '--')<br /> plt.xlabel('Time $t$ [s]')<br /> plt.ylabel('Position $q$ [m], velocity $\dot q$̇ [m/s]')<br /> plt.title('Time plot')<br /> plt.legend(['Position $q$', 'Velocity $v$'])<br /> <br /> #<br /> # (b) Generate a phase plot for the damped oscillator<br /> #<br /> plt.subplot(2, 2, 2)<br /> <br /> ct.phase_plot(<br /> nlspringmass, # dynamics<br /> (-1, 1, 8), (-1, 1, 8), # X, Y range, npoints<br /> scale=0.2,<br /> X0=[[-1, 0.4], [0.1, 1], [1, -0.4], [-0.1, -1]])<br /> <br /> plt.xlabel('Position $q$ [m]')<br /> plt.ylabel('Velocity $\dot q$ [m/s]')<br /> plt.title('Phase portrait')<br /> plt.axis([-1, 1, -1, 1])<br /> <br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.2:_Illustration_of_a_state_model&diff=720 Figure 3.2: Illustration of a state model 2021-08-29T00:56:56Z <p>Murray: </p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.2<br /> |Figure title=Illustration of a state model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-state_model.py<br /> }}<br /> [[Image:figure-3.2-state_model.png|width=480px]]<br /> <br /> '''Figure 3.2''': Illustration of a state model. A state model gives the rate of change of the state as a function of the state. The plot on the left shows the evolution of the state as a function of time. The plot on the right, called a phase portrait, shows the evolution of the states relative to each other, with the velocity of the state denoted by arrows.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.2-state_mode.py - illustration of a state model<br /> # RMM, 2 Jul 2021<br /> #<br /> # Figure 3.2: Illustration of a state model. A state model gives the rate of<br /> # change of the state as a function of the state. The plot on the left shows<br /> # the evolution of the state as a function of time. The plot on the right,<br /> # called a phase portrait, shows the evolution of the states relative to<br /> # each other, with the velocity of the state denoted by arrows.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> #<br /> # Spring mass system with nonlinear dampling<br /> #<br /> # This function gives the dynamics for a dampled oscillator with nonlinear<br /> # damping. The states of the system are<br /> #<br /> # x position<br /> # x velocity<br /> #<br /> # The nonlinear damping is implemented as a change in the linear damping<br /> # coefficient at a small velocity. This is intended to roughly correspond <br /> # to some sort of stiction (and give an interesting phase portrait). The <br /> # default parameters for the system are given by<br /> #<br /> # m = 1 mass, kg<br /> # k = 1 spring constant, N/m<br /> # b1 = 1 damping constant near origin, N-sec/m<br /> # b2 = 0.01 damping constant away from origin, N-sec/m<br /> # dth = 0.5 threshold for switching between damping<br /> #<br /> # This corresponds to a fairly lightly damped oscillator away from the origin.<br /> <br /> def nlspringmass(x, t, u=0, m=1, k=1, b1=2, b2=0.01, dth=0.2):<br /> # Compute the friction force<br /> if abs(x) &lt; dth:<br /> Fb = b1 * x;<br /> elif x &lt; 0:<br /> Fb = -b1 * dth \<br /> + b2 * (x + dth);<br /> else:<br /> Fb = b1 * dth \<br /> + b2 * (x - dth);<br /> <br /> # Return the time derivative of the state<br /> return np.array([x, -k/m * x - Fb/m])<br /> <br /> #<br /> # (a) Simulation of the nonlinear spring mass system<br /> #<br /> plt.subplot(2, 2, 1)<br /> <br /> t = np.linspace(0, 16, 100)<br /> y = sp.integrate.odeint(nlspringmass, [2, 0], t)<br /> <br /> plt.plot(t, y[:, 0], '-', t, y[:, 1], '--')<br /> plt.xlabel('Time $t$ [s]')<br /> plt.ylabel('Position $q$ [m], velocity $\dot q$̇ [m/s]')<br /> plt.title('Time plot')<br /> plt.legend(['Position $q$', 'Velocity $v$'])<br /> <br /> #<br /> # (b) Generate a phase plot for the damped oscillator<br /> #<br /> plt.subplot(2, 2, 2)<br /> <br /> ct.phase_plot(<br /> nlspringmass, # dynamics<br /> (-1, 1, 8), (-1, 1, 8), # X, Y range, npoints<br /> scale=0.2,<br /> X0=[[-1, 0.4], [0.1, 1], [1, -0.4], [-0.1, -1]])<br /> <br /> plt.xlabel('Position $q$ [m]')<br /> plt.ylabel('Velocity $\dot q$ [m/s]')<br /> plt.title('Phase portrait')<br /> plt.axis([-1, 1, -1, 1])<br /> <br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=File:Figure-3.2-state_model.png&diff=719 File:Figure-3.2-state model.png 2021-08-29T00:55:08Z <p>Murray: </p> <hr /> <div></div> Murray http://fbswiki.org/wiki/index.php?title=Figure_3.2:_Illustration_of_a_state_model&diff=718 Figure 3.2: Illustration of a state model 2021-08-29T00:54:29Z <p>Murray: Created page with &quot;{{Figure |Chapter=System Modeling |Figure number=3.2 |Figure title=Illustration of a state model |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-stat...&quot;</p> <hr /> <div>{{Figure<br /> |Chapter=System Modeling<br /> |Figure number=3.2<br /> |Figure title=Illustration of a state model<br /> |GitHub URL=https://github.com/murrayrm/fbs2e-python/blob/main/figure-3.2-state_model.py<br /> }}<br /> [[Image:figure-3.2-state_model.png]]<br /> <br /> '''Figure 3.2''': Illustration of a state model. A state model gives the rate of change of the state as a function of the state. The plot on the left shows the evolution of the state as a function of time. The plot on the right, called a phase portrait, shows the evolution of the states relative to each other, with the velocity of the state denoted by arrows.<br /> <br /> &lt;nowiki&gt;<br /> # figure-3.2-state_mode.py - illustration of a state model<br /> # RMM, 2 Jul 2021<br /> #<br /> # Figure 3.2: Illustration of a state model. A state model gives the rate of<br /> # change of the state as a function of the state. The plot on the left shows<br /> # the evolution of the state as a function of time. The plot on the right,<br /> # called a phase portrait, shows the evolution of the states relative to<br /> # each other, with the velocity of the state denoted by arrows.<br /> #<br /> <br /> import numpy as np<br /> import scipy as sp<br /> import matplotlib.pyplot as plt<br /> import control as ct<br /> <br /> #<br /> # Spring mass system with nonlinear dampling<br /> #<br /> # This function gives the dynamics for a dampled oscillator with nonlinear<br /> # damping. The states of the system are<br /> #<br /> # x position<br /> # x velocity<br /> #<br /> # The nonlinear damping is implemented as a change in the linear damping<br /> # coefficient at a small velocity. This is intended to roughly correspond <br /> # to some sort of stiction (and give an interesting phase portrait). The <br /> # default parameters for the system are given by<br /> #<br /> # m = 1 mass, kg<br /> # k = 1 spring constant, N/m<br /> # b1 = 1 damping constant near origin, N-sec/m<br /> # b2 = 0.01 damping constant away from origin, N-sec/m<br /> # dth = 0.5 threshold for switching between damping<br /> #<br /> # This corresponds to a fairly lightly damped oscillator away from the origin.<br /> <br /> def nlspringmass(x, t, u=0, m=1, k=1, b1=2, b2=0.01, dth=0.2):<br /> # Compute the friction force<br /> if abs(x) &lt; dth:<br /> Fb = b1 * x;<br /> elif x &lt; 0:<br /> Fb = -b1 * dth \<br /> + b2 * (x + dth);<br /> else:<br /> Fb = b1 * dth \<br /> + b2 * (x - dth);<br /> <br /> # Return the time derivative of the state<br /> return np.array([x, -k/m * x - Fb/m])<br /> <br /> #<br /> # (a) Simulation of the nonlinear spring mass system<br /> #<br /> plt.subplot(2, 2, 1)<br /> <br /> t = np.linspace(0, 16, 100)<br /> y = sp.integrate.odeint(nlspringmass, [2, 0], t)<br /> <br /> plt.plot(t, y[:, 0], '-', t, y[:, 1], '--')<br /> plt.xlabel('Time $t$ [s]')<br /> plt.ylabel('Position $q$ [m], velocity $\dot q$̇ [m/s]')<br /> plt.title('Time plot')<br /> plt.legend(['Position $q$', 'Velocity $v$'])<br /> <br /> #<br /> # (b) Generate a phase plot for the damped oscillator<br /> #<br /> plt.subplot(2, 2, 2)<br /> <br /> ct.phase_plot(<br /> nlspringmass, # dynamics<br /> (-1, 1, 8), (-1, 1, 8), # X, Y range, npoints<br /> scale=0.2,<br /> X0=[[-1, 0.4], [0.1, 1], [1, -0.4], [-0.1, -1]])<br /> <br /> plt.xlabel('Position $q$ [m]')<br /> plt.ylabel('Velocity $\dot q$ [m/s]')<br /> plt.title('Phase portrait')<br /> plt.axis([-1, 1, -1, 1])<br /> <br /> plt.tight_layout()<br /> &lt;/nowiki&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=28_Aug_2021:_Links_to_first_edition_supplemental_information_added_to_chapter_pages&diff=717 28 Aug 2021: Links to first edition supplemental information added to chapter pages 2021-08-28T23:35:32Z <p>Murray: Created page with &quot;{{Announcement |Book=FBS |Date=2021/08/28 |Description=Links to supplemental information from the first edition of ''Feedback Systems'' have been added to the chapter pages, t...&quot;</p> <hr /> <div>{{Announcement<br /> |Book=FBS<br /> |Date=2021/08/28<br /> |Description=Links to supplemental information from the first edition of ''Feedback Systems'' have been added to the chapter pages, to allow easy access to additional exercises, frequently asked questions, MATLAB code, and other information.<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Feedback_Principles&diff=716 Feedback Principles 2021-08-28T21:43:22Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=2<br /> |Short name=principles<br /> |Previous chapter=Introduction<br /> |Next chapter=System Modeling<br /> |First edition URL=None<br /> |Chapter summary=This chapter presents examples that illustrate fundamental properties of feed- back: disturbance attenuation, reference signal tracking, robustness to uncertainty, and shaping of behavior. The analysis is based on simple static and dynamical mod- els. After reading this chapter, readers should have some insight into the power of feedback, they should know about transfer functions and block diagrams, and they should be able to design simple feedback systems. The basic concepts described in this chapter are explained in more detail in the remainder of the text, and this chapter can be skipped for readers who prefer to move directly to the more detailed analysis and design techniques.<br /> |Chapter contents=# Nonlinear Static Models<br /> #* Response to Reference Signals<br /> #* Robustness to Parameter Uncertainty<br /> #* Load Disturbance Attenuation<br /> # Linear Dynamical Models<br /> #* Linear Differential Equations and Transfer Functions<br /> #* Stability: The Routh--Hurwitz Criterion<br /> #* Block Diagrams and Transfer Functions<br /> #* Computations Using Transfer Functions<br /> # Using Feedback to Attenuate Disturbances<br /> #* Proportional Control<br /> #* Proportional-Integral (PI) Control<br /> #* Unmodeled Dynamics<br /> # Using Feedback to Track Reference Signals<br /> #* Controllers with Two Degrees of Freedom<br /> # Using Feedback to Provide Robustness<br /> #* Reducing Effects of Parameter Variations and Nonlinearities<br /> #* Nonlinear Analysis and Approximations<br /> # Positive Feedback<br /> #* Hewlett's Oscillator<br /> #* Implementation of Integral Action by Positive Feedback<br /> #* Positive Feedback Combined with Saturation<br /> # Further Reading<br /> :: Exercises<br /> }}<br /> {{Chapter footer}}</div> Murray http://fbswiki.org/wiki/index.php?title=Template:Chapter&diff=715 Template:Chapter 2021-08-28T21:42:48Z <p>Murray: </p> <hr /> <div>&lt;noinclude&gt;<br /> This is the &quot;Chapter&quot; template.<br /> It should be called in the following format:<br /> &lt;pre&gt;<br /> {{Chapter<br /> |Chapter contents=<br /> |Previous chapter=<br /> |Next chapter=<br /> |Chapter number=<br /> |Shortname=<br /> |First edition URL=<br /> |Chapter summary=<br /> |Chapter synopsis=<br /> }}<br /> &lt;/pre&gt;<br /> Edit the page to see the template text.<br /> &lt;/noinclude&gt;&lt;includeonly&gt;<br /> {{Chapter header<br /> |Chapter number={{{Chapter number|?}}}<br /> |Chapter title={{PAGENAME}}<br /> |Previous chapter={{{Previous chapter|FBS2e}}}<br /> |Next chapter={{{Next chapter|FBS2e}}}<br /> }}<br /> <br /> {{{Chapter summary|}}}<br /> <br /> {| border=1 width=100% <br /> |- valign=top style=&quot;padding-top: 0em&quot;<br /> | width=50% style=&quot;padding-left: 0.5em&quot; |<br /> ===Chapter contents===<br /> {{FBS pdf|PDF|fbs-{{{Short name}}}}} ({{FBS date}})<br /> {{{Chapter contents}}}<br /> | width=50% style=&quot;padding-left: 0.5em&quot; |<br /> <br /> === Teaching Materials ===<br /> {{#ask: [[Category:Lectures]] [[Chapter::{{PAGENAME}}]] | format=ul}}<br /> * [[#Additional Exercises|Additional Exercises]]<br /> <br /> === Supplemental Information ===<br /> * [[#Frequently Asked Questions|Frequently Asked Questions]]<br /> * [[#Errata|Errata]]<br /> * [[#Python Code|Python Code]]<br /> * [[#Additional Information|Additional Information]]<br /> {{#ifeq: {{{First edition URL}}} | None | | * [{{{First edition URL}}} First Edition Supplemental Information]}}<br /> |}<br /> <br /> [[Category:Chapter]]<br /> {{#set:<br /> |Number={{{Chapter number}}}<br /> |Previous={{{Previous chapter}}}<br /> |Next={{{Next chapter}}}<br /> }}<br /> &lt;/includeonly&gt;</div> Murray http://fbswiki.org/wiki/index.php?title=Fundamental_Limits&diff=714 Fundamental Limits 2021-08-28T21:41:10Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=14<br /> |Short name=limits<br /> |Previous chapter=Robust Performance<br /> |Next chapter=Architecture and System Design<br /> |First edition URL=None<br /> |Chapter summary=In this chapter we discuss properties that limit performance and robustness of control systems. Non-minimum phase dynamics, due to time delays and right half- plane poles and zeros impose severe limits. There are also nonlinear behaviors that appear at large and small signal levels. Large signal limits can be caused by limited rate and power of actuators, or by constraints required to protect the process. Small signal limits can be caused by measurement noise, friction, and quantization in converters. We also discuss consequences of the limits for loop shaping, and give rules for pole placement design.<br /> |Chapter contents=# System Design Considerations<br /> #* Stabilizability and Strong Stabilizability<br /> #* Right Half-Plane Zeros and Time Delays<br /> # Bode's Integral Formula<br /> #* Derivation of Bode's Integral Formula<br /> # Gain Crossover Frequency Inequality<br /> # The Maximum Modulus Principle<br /> # Robust Pole Placement<br /> #* Fast Stable Process Poles<br /> #* Slow Stable Process Zeros<br /> #* Design Rules for Robust Pole Placement<br /> # Nonlinear Effects<br /> #* Actuation Limits<br /> #* Measurement Noise and Friction<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Fundamental_Limits&diff=713 Fundamental Limits 2021-08-28T21:36:59Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=14<br /> |Short name=limits<br /> |Previous chapter=Robust Performance<br /> |Next chapter=Architecture and System Design<br /> |Chapter summary=In this chapter we discuss properties that limit performance and robustness of control systems. Non-minimum phase dynamics, due to time delays and right half- plane poles and zeros impose severe limits. There are also nonlinear behaviors that appear at large and small signal levels. Large signal limits can be caused by limited rate and power of actuators, or by constraints required to protect the process. Small signal limits can be caused by measurement noise, friction, and quantization in converters. We also discuss consequences of the limits for loop shaping, and give rules for pole placement design.<br /> |Chapter contents=# System Design Considerations<br /> #* Stabilizability and Strong Stabilizability<br /> #* Right Half-Plane Zeros and Time Delays<br /> # Bode's Integral Formula<br /> #* Derivation of Bode's Integral Formula<br /> # Gain Crossover Frequency Inequality<br /> # The Maximum Modulus Principle<br /> # Robust Pole Placement<br /> #* Fast Stable Process Poles<br /> #* Slow Stable Process Zeros<br /> #* Design Rules for Robust Pole Placement<br /> # Nonlinear Effects<br /> #* Actuation Limits<br /> #* Measurement Noise and Friction<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Fundamental_Limits&diff=712 Fundamental Limits 2021-08-28T21:36:01Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=14<br /> |Short name=limits<br /> |Previous chapter=Robust Performance<br /> |Next chapter=Architecture and System Design<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Robust_Performance#Frequently_Asked_Questions<br /> |Chapter summary=In this chapter we discuss properties that limit performance and robustness of control systems. Non-minimum phase dynamics, due to time delays and right half- plane poles and zeros impose severe limits. There are also nonlinear behaviors that appear at large and small signal levels. Large signal limits can be caused by limited rate and power of actuators, or by constraints required to protect the process. Small signal limits can be caused by measurement noise, friction, and quantization in converters. We also discuss consequences of the limits for loop shaping, and give rules for pole placement design.<br /> |Chapter contents=# System Design Considerations<br /> #* Stabilizability and Strong Stabilizability<br /> #* Right Half-Plane Zeros and Time Delays<br /> # Bode's Integral Formula<br /> #* Derivation of Bode's Integral Formula<br /> # Gain Crossover Frequency Inequality<br /> # The Maximum Modulus Principle<br /> # Robust Pole Placement<br /> #* Fast Stable Process Poles<br /> #* Slow Stable Process Zeros<br /> #* Design Rules for Robust Pole Placement<br /> # Nonlinear Effects<br /> #* Actuation Limits<br /> #* Measurement Noise and Friction<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Robust_Performance&diff=711 Robust Performance 2021-08-28T21:35:53Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=13<br /> |Short name=robperf<br /> |Previous chapter=Frequency Domain Design<br /> |Next chapter=Fundamental Limits<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Robust_Performance#Frequently_Asked_Questions<br /> |Chapter summary=This chapter focuses on the analysis of robustness of feedback systems, a vast topic for which we provide only an introduction to some of the key concepts. We consider the stability and performance of systems whose process dynamics are uncertain. We make use of generalizations of Nyquist’s stability criterion as a mechanism to characterize robust stability and performance. To do this we develop ways to describe uncertainty, both in the form of parameter variations and in the form of neglected dynamics. We also briefly mention some methods for designing controllers to achieve robust performance.<br /> |Chapter contents=# Modeling Uncertainty<br /> #* Parametric Uncertainty<br /> #* Unmodeled Dynamics<br /> #* When Are Two Systems Similar?<br /> #* The Vinnicombe Metric<br /> # Stability in the Presence of Uncertainty<br /> #* Robust Stability Using Nyquist's Criterion<br /> #* Youla Parameterization<br /> # Performance in the Presence of Uncertainty<br /> #* Disturbance Attenuation<br /> #* Response to Reference Signals<br /> # Design for Robust Performance<br /> #* Quantitative Feedback Theory<br /> #* Linear Quadratic Control<br /> #* $H\relax \p@index \infty$ Control<br /> #* The Generalized Stability Margin<br /> #* Disturbance Weighting<br /> #* Limits of Robust Design<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Frequency_Domain_Design&diff=710 Frequency Domain Design 2021-08-28T21:35:31Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=12<br /> |Short name=loopsyn<br /> |Previous chapter=PID Control<br /> |Next chapter=Robust Performance<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Frequency_Domain_Design#Frequently_Asked_Questions<br /> |Chapter summary=In this chapter we continue to explore the use of frequency domain techniques with a focus on the design of feedback systems. We begin with a more thorough description of the performance specifications for control systems and then introduce the concept of “loop shaping” as a mechanism for designing controllers in the frequency domain. Additional techniques discussed in this chapter include feedforward compensation, the root locus method, and nested controller design.<br /> |Chapter contents=# Sensitivity Functions<br /> # Performance Specifications<br /> #* Response to Reference Signals<br /> #* Response to Load Disturbances and Measurement Noise<br /> #* Measuring Specifications<br /> # Feedback Design via Loop Shaping<br /> #* Design Considerations<br /> #* Lead and Lag Compensation<br /> # Feedforward Design<br /> #* Combining Feedforward and Feedback<br /> #* Difficulties with Feedforward<br /> #* Approximate Inverses<br /> # The Root Locus Method<br /> # Design Example<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=PID_Control&diff=709 PID Control 2021-08-28T21:35:14Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=11<br /> |Short name=pid<br /> |Previous chapter=Frequency Domain Analysis<br /> |Next chapter=Frequency Domain Design<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=PID_Control#Frequently_Asked_Questions<br /> |Chapter summary=Proportional-integral-derivative (PID) control is by far the most common way of using feedback in engineering systems. In this chapter we present the basic properties of PID control and the methods for choosing the parameters of the controllers. We also analyze the effects of actuator saturation, an important feature of many feedback systems, and describe methods for compensating for it. Finally, we discuss the implementation of PID controllers as an example of how to implement feedback control systems using analog or digital computation.<br /> |Chapter contents=# Basic Control Functions<br /> # Simple Controllers for Complex Systems<br /> # PID Tuning<br /> #* Ziegler--Nichols' Tuning<br /> #* Tuning Based on the FOTD Model<br /> #* Relay Feedback<br /> # Integral Windup<br /> #* Avoiding Windup<br /> #* Manual Control and Tracking<br /> #* Anti-Windup for General Controllers<br /> # Implementation<br /> #* Filtering the Derivative<br /> #* Setpoint Weighting<br /> #* Implementation Based on Operational Amplifiers<br /> #* Computer Implementation<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Frequency_Domain_Analysis&diff=708 Frequency Domain Analysis 2021-08-28T21:34:45Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=10<br /> |Short name=loopanal<br /> |Previous chapter=Transfer Functions<br /> |Next chapter=PID Control<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Frequency_Domain_Analysis#Frequently_Asked_Questions<br /> |Chapter summary=In this chapter we study how the stability and robustness of closed loop systems can be determined by investigating how sinusoidal signals of different frequencies propagate around the feedback loop. This technique allows us to reason about the closed loop behavior of a system through the frequency domain properties of the open loop transfer function. The Nyquist stability theorem is a key result that provides a way to analyze stability and introduce measures of degrees of stability.<br /> |Chapter contents=# The Loop Transfer Function<br /> # The Nyquist Criterion<br /> #* The Nyquist Plot<br /> #* The General Nyquist Criterion<br /> #* Conditional Stability<br /> # Stability Margins<br /> # Bode's Relations and Minimum Phase Systems<br /> # Generalized Notions of Gain and Phase<br /> #* System Gain and Passivity<br /> #* Extensions of the Nyquist Criterion<br /> #* Describing Functions<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Transfer_Functions&diff=707 Transfer Functions 2021-08-28T21:34:13Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=9<br /> |Short name=xferfcns<br /> |Previous chapter=Output Feedback<br /> |Next chapter=Frequency Domain Analysis<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Transfer_Functions#Frequently_Asked_Questions<br /> |Chapter summary=This chapter introduces the concept of the transfer function, which is a com- pact description of the input/output relation for a linear time-invariant system. We show how to obtain transfer functions analytically and experimentally. Combining transfer functions with block diagrams gives a powerful algebraic method to analyze linear systems with many blocks. The transfer function allows new interpretations of system dynamics. We also introduce the Bode plot, a powerful graphical rep- resentation of the transfer function that was introduced by Bode to analyze and design feedback amplifiers.<br /> |Chapter contents=# The Loop Transfer Function<br /> # The Nyquist Criterion<br /> #* The Nyquist Plot<br /> #* The General Nyquist Criterion<br /> #* Conditional Stability<br /> # Stability Margins<br /> # Bode's Relations and Minimum Phase Systems<br /> # Generalized Notions of Gain and Phase<br /> #* System Gain and Passivity<br /> #* Extensions of the Nyquist Criterion<br /> #* Describing Functions<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=Output_Feedback&diff=706 Output Feedback 2021-08-28T21:33:55Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=8<br /> |Short name=outputfbk<br /> |Previous chapter=State Feedback<br /> |Next chapter=Transfer Functions<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Output_Feedback#Frequently_Asked_Questions<br /> |Chapter summary=In this chapter we show how to use output feedback to modify the dynamics of the system through the use of observers. We introduce the concept of observability and show that if a system is observable, it is possible to recover the state from measurements of the inputs and outputs to the system. We then show how to design a controller with feedback from the observer state. A general controller with two degrees of freedom is obtained by adding feedforward. We illustrate by outlining a controller for a nonlinear system that also employs gain scheduling.<br /> |Chapter contents=# Frequency Domain Modeling<br /> # Determining the Transfer Function<br /> #* Transmission of Exponential Signals<br /> #* Transfer Functions for Linear Differential Equations<br /> #* Time Delays and Partial Differential Equations<br /> #* State Space Realizations of Transfer Functions<br /> # Laplace Transforms<br /> # Block Diagrams and Transfer Functions<br /> #* Control System Transfer Functions<br /> #* Algebraic Loops<br /> # Zero Frequency Gain, Poles, and Zeros<br /> #* Zero Frequency Gain<br /> #* Poles and Zeros<br /> #* Pole/Zero Cancellations<br /> # The Bode Plot<br /> #* Sketching and Interpreting Bode Plots<br /> #* Poles and Zeros in the Right Half-Plane<br /> #* System Insights from the Bode Plot<br /> #* Determining Transfer Functions Experimentally<br /> # Further Reading<br /> :: Exercises<br /> }}</div> Murray http://fbswiki.org/wiki/index.php?title=State_Feedback&diff=705 State Feedback 2021-08-28T21:33:30Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=7<br /> |Short name=statefbk<br /> |Previous chapter=Linear Systems<br /> |Next chapter=Output Feedback<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=State_Feedback#Additional_Exercises<br /> |Chapter summary=This chapter describes how feedback can be used to shape the local behavior of a system. The concept of reachability is introduced and used to investigate how to &quot;design&quot; the dynamics of a system through placement of its eigenvalues. In particular, it will be shown that under certain conditions it is possible to assign the system eigenvalues to arbitrary values by appropriate feedback of the system state.<br /> |Chapter contents=# Observability<br /> #* Definition of Observability<br /> #* Testing for Observability<br /> #* Observable Canonical Form<br /> # State Estimation<br /> #* The Observer<br /> #* Computing the Observer Gain<br /> # Control Using Estimated State<br /> #* Kalman's Decomposition of a Linear System<br /> # Kalman Filtering<br /> #* Discrete-Time Systems<br /> #* Continuous-Time Systems<br /> #* Linear Quadratic Gaussian Control (LQG)<br /> # State Space Controller Design<br /> #* Two Degree-of-Freedom Controller Architecture<br /> #* Feedforward Design and Trajectory Generation<br /> #* Disturbance Modeling and State Augmentation<br /> #* Feedback Design and Gain Scheduling<br /> #* Nonlinear Estimation<br /> #* Computer Implementation<br /> # Further Reading<br /> :: Exercises<br /> }}<br /> == Chapter Summary ==<br /> This chapter describes how state feedback can be used to design the (closed loop) dynamics of the system:<br /> &lt;ol&gt;<br /> &lt;li&gt; &lt;p&gt; A linear system with dynamics<br /> &lt;center&gt;&lt;math&gt;<br /> \begin{aligned}<br /> \dot x &amp;= A x + B u &amp;\quad x &amp;\in \mathbb{R}^n, u \in \mathbb{R} \\<br /> y &amp;= C x + D u &amp;\quad y &amp;\in \mathbb{R}<br /> \end{aligned}<br /> &lt;/math&gt;&lt;/center&gt;<br /> is said to be ''reachable'' if we can find an input &lt;math&gt;u(t)&lt;/math&gt; defined on the interval &lt;math&gt;[0, T]&lt;/math&gt; that can steer the system from a given final point &lt;math&gt;x(0) = x_0&lt;/math&gt; to a desired final point &lt;math&gt;x(T) = x_f&lt;/math&gt;.<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;The ''reachability matrix'' for a linear system is given by<br /> &lt;center&gt;&lt;math&gt;<br /> W_r = \left[\begin{matrix} B &amp; AB &amp; \cdots &amp; A^{n-1}B \end{matrix}\right].<br /> &lt;/math&gt;&lt;/center&gt;<br /> A linear system is reachable if and only if the reachability matrix &lt;math&gt;W_\text{r}&lt;/math&gt; is invertible (assuming a single intput/single output system). Systems that are not reachable have states that are constrained to have a fixed relationship with each other.<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;A linear system of the form<br /> &lt;center&gt;&lt;math&gt;<br /> \frac{dz}{dt}=<br /> \left[\begin{matrix}<br /> -a_1 &amp; -a_2 &amp; -a_3 &amp; \dots &amp; -a_n \\<br /> 1 &amp; 0 &amp; 0 &amp; \dots &amp; 0 \\<br /> 0 &amp; 1 &amp; 0 &amp; \dots &amp; 0 \\<br /> \vdots &amp; &amp; \ddots &amp; \ddots &amp; \vdots \\<br /> 0 &amp; &amp; &amp; 1 &amp; 0\\<br /> \end{matrix}\right] z+ \left[\begin{matrix}<br /> 1 \\ 0 \\ 0 \\ \vdots \\ 0 <br /> \end{matrix}\right] u <br /> &lt;/math&gt;&lt;/center&gt;<br /> is said to be in ''reachable canonical form''. A system in this form is always reachable and has a characteristic polynomial given by<br /> &lt;center&gt;&lt;math&gt;<br /> \det(sI-A) = s^n+a_1 s^{n-1} + \cdots + a_{n-1}s + a_n,<br /> &lt;/math&gt;&lt;/center&gt;<br /> A reachable linear system can be transformed into reachable canonical form through the use of a coordinate transformation &lt;math&gt;z = T x&lt;/math&gt;. <br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;A state feedback law has the form<br /> &lt;center&gt;&lt;math&gt;<br /> u = -K x + k_r r<br /> &lt;/math&gt;&lt;/center&gt;<br /> where &lt;math&gt;r&lt;/math&gt; is the reference value for the output. The closed loop dynamics for the system are given by<br /> &lt;center&gt;&lt;math&gt;<br /> \dot x = (A - B K) x + B k_\text{f} r.<br /> &lt;/math&gt;&lt;/center&gt;<br /> The stability of the system is determined by the stability of the matrix &lt;math&gt;A - BK&lt;/math&gt;. The equilibrium point and steady state output (assuming the systems is stable) are given by<br /> &lt;center&gt;&lt;math&gt;<br /> x_e = -(A-BK)^{-1} B k_\text{f} r \qquad y_e = C x_e.<br /> &lt;/math&gt;&lt;/center&gt;<br /> Choosing &lt;math&gt;k_\text{f}&lt;/math&gt; as<br /> &lt;center&gt;&lt;math&gt;<br /> k_r = {-1}/\left(C (A-BK)^{-1} B\right).<br /> &lt;/math&gt;&lt;/center&gt;<br /> gives &lt;math&gt;y_e = r&lt;/math&gt;.&lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;If a system is reachable, then there exists a feedback law of the form<br /> &lt;center&gt;&lt;math&gt;<br /> u = -K x + k_\text{f} r<br /> &lt;/math&gt;&lt;/center&gt;<br /> the gives a closed loop system with an arbitrary characteristic polynomial. Hence the eigenvalues of a reachable linear system can be placed arbitrarily through the use of an appropriate feedback control law.<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;''Integral feedback'' can be used to provide zero steady state error instead of careful calibration of the gain &lt;math&gt;k_\text{f}&lt;/math&gt;. An integral feedback controller has the form<br /> &lt;center&gt;&lt;math&gt;<br /> u = -K (x - x_\text{e}) - k_\text{i} z + k_\text{f} r,<br /> &lt;/math&gt;&lt;/center&gt;<br /> where<br /> &lt;center&gt;&lt;math&gt;<br /> \dot z = y - r<br /> &lt;/math&gt;&lt;/center&gt;<br /> is the integral error. The gains &lt;math&gt;K&lt;/math&gt;, &lt;math&gt;k_i&lt;/math&gt; and &lt;math&gt;k_\text{f}&lt;/math&gt; can be found by designing a stabilizing state feedback for the system dynamics augmented by the integrator dynamics.<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;A ''linear quadratic regulator'' minimizes the cost function<br /> &lt;center&gt;&lt;math&gt;<br /> \tilde J = \int_0^\infty \left(x^T Q_x x + u^T Q_u u \right)\,dt.<br /> &lt;/math&gt;&lt;/center&gt;<br /> The solution to the LQR problem is given by a linear control law of<br /> the form<br /> &lt;center&gt;&lt;math&gt;<br /> u = -Q_u^{-1} B^T S x.<br /> &lt;/math&gt;&lt;/center&gt;<br /> where &lt;math&gt;S \in \mathbb{R}^{n \times n}&lt;/math&gt; is a positive definite, symmetric<br /> matrix that satisfies the equation<br /> &lt;center&gt;&lt;math&gt;<br /> S A + A^T S - S B Q_u^{-1} B^T S + Q_x = 0.<br /> &lt;/math&gt;&lt;/center&gt;<br /> This equation is called the ''algebraic Riccati equation'' and can be solved numerically.<br /> &lt;/p&gt;&lt;/li&gt;<br /> &lt;/ol&gt;<br /> <br /> {{Chapter footer}}</div> Murray http://fbswiki.org/wiki/index.php?title=Linear_Systems&diff=704 Linear Systems 2021-08-28T21:33:02Z <p>Murray: </p> <hr /> <div>{{Chapter<br /> |Chapter number=6<br /> |Short name=linsys<br /> |Previous chapter=Dynamic Behavior<br /> |Next chapter=State Feedback<br /> |First edition URL=https://www.cds.caltech.edu/~murray/amwiki/index.php?title=Linear_Systems#Frequently_Asked_Questions<br /> |Chapter summary=Previous chapters have focused on the dynamics of a system with relatively little attention to the inputs and outputs. This chapter gives an introduction to input/output behavior for linear systems and shows how a nonlinear system can be approximated near an equilibrium point by a linear model.<br /> |Chapter contents=# Reachability<br /> #* Definition of Reachability<br /> #* Testing for Reachability<br /> #* Reachable Canonical Form<br /> # Stabilization by State Feedback<br /> #* State Space Controller Structure<br /> #* State Feedback for Systems in Reachable Canonical Form<br /> #* Eigenvalue Assignment<br /> # Design Considerations<br /> #* Second-Order Systems<br /> #* Higher-Order Systems<br /> # Integral Action<br /> #* System Augmentation<br /> #* Reachability of the Augmented System<br /> # Linear Quadratic Regulators<br /> # Further Reading<br /> :: Exercises<br /> }}<br /> == Chapter Summary ==<br /> This chapter introduces the analysis tools for linear input/output systems.<br /> &lt;ol&gt;<br /> &lt;li&gt; &lt;p&gt;A ''linear system'' is one in which the output is jointly linear in the intitial condition for the system and the input to the system. In particular, a linear system has the property that if we apply an input &lt;math&gt;u(t) = \alpha u_1(t) + \beta u_2(t)&lt;/math&gt; with zero initial condition, the corresponding output will be &lt;math&gt;y(t) = \alpha y_1(t) + \beta y_2(t)&lt;/math&gt;, where &lt;math&gt;y_i&lt;/math&gt; is the output associated with the input &lt;math&gt;u_i&lt;/math&gt;. This propery is called linear ''superposition''.&lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;&lt;span id=SISO&gt;A differential equation of the form<br /> &lt;center&gt;&lt;math&gt;<br /> \begin{aligned}<br /> \dot x &amp;= A x + B u &amp;\quad x &amp;\in R^n, u \in R \\<br /> y &amp;= C x + D u &amp; y &amp;\in R<br /> \end{aligned}<br /> &lt;/math&gt;&lt;/center&gt;<br /> is a ''single-input, single-output'' (SISO) ''linear differential equation''&lt;/span&gt;. Its solution can be written in terms of the ''[[matrix exponential]]''<br /> &lt;center&gt;&lt;math&gt;<br /> e^{At}=I+At+\frac{1}{2}A^2t^2+\frac{1}{3!}A^3t^3+\cdots=\sum_{k=0}^\infty \frac{1}{k!} A^kt^k.<br /> &lt;/math&gt;&lt;/center&gt;<br /> The solution to the differential equation is given by the ''convolution equation''<br /> &lt;center&gt;&lt;math&gt;<br /> y(t) = C e^{At} x(0) + \int_0^t C e^{A(t-\tau)}B u(\tau) d\tau + Du(t). <br /> &lt;/math&gt;&lt;/center&gt;<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;A linear system <br /> &lt;center&gt;&lt;math&gt;\dot x = A x&lt;/math&gt;&lt;/center&gt; <br /> is [[Dynamic Behavior#stability|asymptotically stable]] if and only if all eigenvalues of &lt;math&gt;A&lt;/math&gt; all have strictly negative real part and is [[Dynamic Behavior#stability|unstable]] if any eigenvalue of &lt;math&gt;A&lt;/math&gt; has strictly positive real part. For systems with eigenvalues having zero real-part, stability is determined by using the ''[http://en.wikipedia.org/wiki/Jordan_normal_form Jordan normal form]'' associated with the matrix. A system with eigenvalues that have no strictly positive real part is stable if and only if the Jordan block corresponding to each eigenvalue with zero part is a scalar (1x1) block.&lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;The input/output response of a (stable) linear system contains a transient region portion, which eventually decays to zero, and a steady state portion, which persists over time. Two special responses are the ''step response'', which is the output corresponding to an step input applied at &lt;math&gt;t = 0&lt;/math&gt; and the ''frequency response'', which is the response of the system to a sinusoidal input at a given frequency.&lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;<br /> The step response is characterized by the following parameters:<br /> * The ''steady state value'', &lt;math&gt;y_\text{ss}&lt;/math&gt;, of a step response is the final level of the output, assuming it converges.<br /> * The ''rise time'', &lt;math&gt;T_\text{r}&lt;/math&gt;, is the amount of time required for the signal to go from 10% of its final value to 90% of its final value.<br /> * The ''overshoot'', &lt;math&gt;M_\text{p}&lt;/math&gt;, is the percentage of the initial value by which the signal initially rises above the final value.<br /> * The ''settling time'', &lt;math&gt;T_\text{s}&lt;/math&gt;, is the amount of time required for the signal to stay within 5% of its final value for all future times.<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;The frequency response is given by<br /> &lt;center&gt;&lt;math&gt;<br /> y(t) = \underbrace{C e^{At} \Bigl( x(0)-(s I-A)^{-1} B<br /> \Bigr)}_{\text{transient}} + <br /> \underbrace{\Bigl( D+C(s I-A)^{-1}B \Bigr) e^{s<br /> t}}_{\text{steady state}},<br /> &lt;/math&gt;&lt;/center&gt;<br /> where &lt;math&gt;\cos\omega t = \frac{1}{2} \left(e^{j \omega t} + e^{-j \omega t}\right)&lt;/math&gt; and &lt;math&gt;s = i \omega&lt;/math&gt;. The gain and phase of the frequency response are given by<br /> &lt;center&gt;&lt;math&gt;<br /> \text{gain}(\omega) = \frac{A_y}{A_u} = M \qquad<br /> \text{phase}(\omega) = \phi - \psi = \theta.<br /> &lt;/math&gt;&lt;/center&gt;<br /> &lt;/p&gt;&lt;/li&gt;<br /> <br /> &lt;li&gt;&lt;p&gt;A nonlinear system of the form<br /> &lt;center&gt;&lt;math&gt;<br /> \begin{aligned}<br /> \dot x &amp;= f(x, u) &amp;\quad x &amp;\in \mathbb{R}^n, u \in \mathbb{R} \\<br /> y &amp;= h(x, u) &amp; y &amp;\in \mathbb{R}<br /> \end{aligned}<br /> &lt;/math&gt;&lt;/center&gt;<br /> is a single-input, single-output (SISO) nonlinear system. It can be linearized about an equibrium point &lt;math&gt;x = x_\text{e}&lt;/math&gt;, &lt;math&gt;u = u_\text{e}&lt;/math&gt;, &lt;math&gt;y = y_\text{e}&lt;/math&gt; by defining new variables<br /> &lt;center&gt;&lt;math&gt;<br /> z = x - x_\text{e}e \qquad v = u - u_\text{e} \qquad w = y - h(x_\text{e}, u_\text{e}).<br /> &lt;/math&gt;&lt;/center&gt;<br /> The dynamics of the system near the equilibrium point can then be approximated by the linear system<br /> &lt;center&gt;&lt;math&gt;<br /> \begin{aligned}<br /> \dot x &amp;= A x + B u, \\<br /> y &amp;= C x + D u,<br /> \end{aligned}<br /> &lt;/math&gt;&lt;/center&gt;<br /> where<br /> &lt;center&gt;&lt;math&gt;<br /> \begin{aligned}<br /> A &amp;=\left.\frac{\partial f(x, u)}{\partial x}\right|_{x_\text{e}, u_\text{e}} &amp;\quad<br /> B &amp;= \left.\frac{\partial f(x, u)}{\partial u}\right|_{x_\text{e}, u_\text{e}} \\<br /> C &amp;= \left.\frac{\partial h(x, u)}{\partial x}\right|_{x_\text{e}, u_\text{e}} &amp;\quad<br /> D &amp;= \left.\frac{\partial y(x, u)}{\partial u}\right|_{x_\text{e}, u_\text{e}}<br /> \end{aligned}<br /> &lt;/math&gt;&lt;/center&gt;<br /> The equilibrium point for a nonlinear system is locally asymptotically stable if the real part of the eigenvalues of the linearization about that equilibrium point have strictly negative real part.<br /> &lt;/p&gt;&lt;/li&gt;<br /> &lt;/ol&gt;<br /> <br /> {{Chapter footer}}</div> Murray