-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcruise.py
124 lines (98 loc) · 4.07 KB
/
cruise.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# cruise.py - Cruise control dynamics and control
# RMM, 20 Jun 2021
import numpy as np
import matplotlib.pyplot as plt
from math import pi
import control as ct
#
# Vehicle model
#
# The dynamics for this system are implemented using the I/O systems module
# in python-control. This model is described in detail in Section 4.1 of
# FBS2e.
#
# Engine model
def motor_torque(omega, params={}):
# Set up the system parameters
Tm = params.get('Tm', 190.) # engine torque constant
omega_m = params.get('omega_m', 420.) # peak engine angular speed
beta = params.get('beta', 0.4) # peak engine rolloff
return np.clip(Tm * (1 - beta * (omega/omega_m - 1)**2), 0, None)
# Vehicle dynamics
def vehicle_update(t, x, u, params={}):
"""Vehicle dynamics for cruise control system.
Parameters
----------
x : array
System state: car velocity in m/s
u : array
System input: [throttle, gear, road_slope], where throttle is
a float between 0 and 1, gear is an integer between 1 and 5,
and road_slope is in rad.
Returns
-------
float
Vehicle acceleration
"""
from math import copysign, sin
sign = lambda x: copysign(1, x) # define the sign() function
# Set up the system parameters
m = params.get('m', 1600.) # vehicle mass, kg
g = params.get('g', 9.8) # gravitational constant, m/s^2
Cr = params.get('Cr', 0.01) # coefficient of rolling friction
Cd = params.get('Cd', 0.32) # drag coefficient
rho = params.get('rho', 1.3) # density of air, kg/m^3
A = params.get('A', 2.4) # car area, m^2
alpha = params.get(
'alpha', [40, 25, 16, 12, 10]) # gear ratio / wheel radius
# Define variables for vehicle state and inputs
v = x[0] # vehicle velocity
throttle = np.clip(u[0], 0, 1) # vehicle throttle
gear = u[1] # vehicle gear
theta = u[2] # road slope
# Force generated by the engine
omega = alpha[int(gear)-1] * v # engine angular speed
F = alpha[int(gear)-1] * motor_torque(omega, params) * throttle
# Disturbance forces
#
# The disturbance force Fd has three major components: Fg, the forces due
# to gravity; Fr, the forces due to rolling friction; and Fa, the
# aerodynamic drag.
# Letting the slope of the road be \theta (theta), gravity gives the
# force Fg = m g sin \theta.
Fg = m * g * sin(theta)
# A simple model of rolling friction is Fr = m g Cr sgn(v), where Cr is
# the coefficient of rolling friction and sgn(v) is the sign of v (±1) or
# zero if v = 0.
Fr = m * g * Cr * sign(v)
# The aerodynamic drag is proportional to the square of the speed: Fa =
# 1/2 \rho Cd A |v| v, where \rho is the density of air, Cd is the
# shape-dependent aerodynamic drag coefficient, and A is the frontal area
# of the car.
Fa = 1/2 * rho * Cd * A * abs(v) * v
# Final acceleration on the car
Fd = Fg + Fr + Fa
dv = (F - Fd) / m
return dv
# Vehicle input/output model
vehicle_dynamics = ct.nlsys(
vehicle_update, None, name='vehicle',
inputs = ['u', 'gear', 'theta'], outputs = ['v'], states=['v'])
#
# PI controller
#
# The controller for the system is designed in Example XX, but is included
# here since it is needed for some earlier examples.
#
# Nominal controller design for remaining analyses
# Construct a PI controller with rolloff, as a transfer function
Kp = 0.5 # proportional gain
Ki = 0.1 # integral gain
PI_control = ct.tf(
[Kp, Ki], [1, 0.01*Ki/Kp], name='control', inputs='u', outputs='y')
cruise_PI = ct.interconnect(
(vehicle_dynamics, PI_control), name='cruise',
connections = [['control.u', '-vehicle.v'], ['vehicle.u', 'control.y']],
inplist = ['control.u', 'vehicle.gear', 'vehicle.theta'],
inputs = ['vref', 'gear', 'theta'],
outlist = ['vehicle.v', 'vehicle.u'], outputs = ['v', 'u'])