#!/usr/bin/env python # coding: utf-8 # # *This notebook contains course material from [CBE30338](https://jckantor.github.io/CBE30338) # by Jeffrey Kantor (jeff at nd.edu); the content is available [on Github](https://github.com/jckantor/CBE30338.git). # The text is released under the [CC-BY-NC-ND-4.0 license](https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode), # and code is released under the [MIT license](https://opensource.org/licenses/MIT).* # # < [Getting Started with Transfer Functions](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/05.01-Getting-Started-with-Transfer-Functions.ipynb) | [Contents](toc.ipynb) | [Creating Bode Plots](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/05.03-Creating-Bode-Plots.ipynb) >

Open in Colab

Download # # Closed-Loop Transfer Functions for Car Cruise Control # # ## Summary # # Block diagrams allow you to visualize the flow of information in complex dynamical systems. Using simple elements, it is possible to create models to study the relationship between control structure, process response, and control action. # # The purpose of this notebook is to introduce for the analysis of block diagrams made up of linear transfer functions. # ## Block Diagram for Car Cruise Control # # Let's imagine you own a car with a mass of 1,500 kg (including passengers) that is traveling down a level stretch of highway at a desired speed of 100 kilometers per hour. You wish to design a cruise controller that will adjust the throttle position $u$ within the limits 0 to 1 in order to maintain constant speed. # # A block diagram for this system is shown in the following sketch: # # ![Cruise Control Block Diagram](figures/CruiseControl.png) # # The disturbance to the system is a change in road grade measured in percent. (A one percent grade corresponds to 1 foot of rise in 100 feet of horizontal travel, or a tangent of 0.01). The dynamics are represented by three transfer functions denoting the response of the engine torque to throttle position, # # $$G_e = \frac{600}{s + 1}$$ # # the response of the vehicle to engine and external forces, # # $$G_v = \frac{0.5}{5s + 1}$$ # # and the dynamics of the speed measurement, # # $$G_m = \frac{1}{0.2s + 1}$$ # # We assume that a one percent increase in grade introduces 150 Newtons of force in opposing the car acceleration, that is # # $$G_d = 150$$ # # The controller is assumed to be a proportional-integral control written as # # $$G_c = K_c\left(1 + \frac{1}{\tau_I s}\right)$$ # # This can be summarized in the following block diagram # # ![Cruise Control Block Diagram](figures/CruiseControl2.png) # In[1]: get_ipython().run_line_magic('matplotlib', 'inline') import numpy as np import seaborn as sns import matplotlib.pyplot as plt import control.matlab as control # control constants Kc = 0.01 tauI = 10 # control transfer function Gc = Kc*control.tf([tauI,1],[tauI,0]) # model transfer functions Gd = control.tf([150],[1]) Ge = control.tf([600],[1,1]) Gv = control.tf([0.5],[5,1]) Gm = control.tf([1],[0.2,1]) # ## Closed-Loop Transfer Functions # # Vehicle response to a change in setpoint: # # $$H_{yr} = \frac{G_vG_eG_c}{1+G_vG_eG_cG_m}$$ # # Vehicle response to a disturbance: # # $$H_{yd} = -\frac{G_vG_d}{1+G_vG_eG_cG_m}$$ # # Throttle response to a change in setpoint: # # $$H_{ur} = \frac{G_c}{1+G_cG_mG_vG_e}$$ # # Throttle response to a disturbance: # # $$H_{ud} = \frac{G_cG_mG_vG_d}{1+G_cG_mG_vG_e}$$ # # In[2]: Hyr = Gv*Ge*Gc/(1+Gv*Ge*Gc*Gm) Hyd = -Gv*Gd/(1+Gv*Ge*Gc*Gm) Hur = Gc/(1+Gc*Gm*Gv*Ge) Hud = Gc*Gm*Gv*Gd/(1+Gc*Gm*Gv*Ge) # In[3]: print(Hyr) # In[4]: print(Hyd) # In[5]: print(Hur) # In[6]: print(Hud) # ## Step Responses # In[7]: t = np.linspace(0,100,1000) plt.figure(figsize=(12,8)) plt.subplot(2,2,1) yr,t = control.step(Hyr,t) plt.plot(t,yr) plt.xlabel('Time [sec]') plt.ylabel('Speed [kph]') plt.title('Response to a Setpoint Change') plt.subplot(2,2,2) yd,t = control.step(Hyd,t) plt.plot(t,yd) plt.xlabel('Time [sec]') plt.ylabel('Speed [kph]') plt.title('Response to a Disturbance') plt.subplot(2,2,3) ur,t = control.step(Hur,t) plt.plot(t,ur) plt.xlabel('Time [sec]') plt.ylabel('Throttle Setting') plt.subplot(2,2,4) ud,t = control.step(Hud,t) plt.plot(t,ud) plt.xlabel('Time [sec]') plt.ylabel('Throttle Setting') # ## Additional Examples # ### Internal Model Control # # Internal model control is a version of feedback control that incorporates an explicit process model. A simple block diagram of internal model control is given by # # ![Internal Model Control](./figures/Internal_Model_Control.png) # # There are two designated inputs, the reference $w$ and disturbance $y_d$, and three labeled signals $u$, $y$, and $d$ that appear relevant to closed-loop performance. Here's the solution for all six closed-loop transfer transfer functions: # # | Output\Input | $w$ | $y_d$ | # | :----------: | :-: | :---: | # | $u$ | $\frac{Q}{1 + Q(G - G_m)}$ | $-\frac{Q}{1 + Q(G - G_m)}$ | # | $y$ | $\frac{GQ}{1 + Q(G - G_m)}$ | $\frac{1}{1 + Q(G - G_m)}$ | # | $d$ | $\frac{(G-G_m)Q}{1 + Q(G - G_m)}$ | $\frac{1}{1 + Q(G - G_m)}$ | # # ### SEMD Figure 11-14 # # ![Internal Model Control](figures/E11-10.png) # # # $$H_{yd} = \frac{G_3}{1+(G_2 + G_3G_1)K_cK_m}$$ # # $$H_{yr} = \frac{(G_2+G_3G_1)K_cK_m}{1+(G_2 + G_3G_1)K_cK_m}$$ # # # # In[ ]: # # < [Getting Started with Transfer Functions](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/05.01-Getting-Started-with-Transfer-Functions.ipynb) | [Contents](toc.ipynb) | [Creating Bode Plots](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/05.03-Creating-Bode-Plots.ipynb) >

Open in Colab

Download