Skip to content

Commit 61a1be5

Browse files
committed
Merge branch 'master' of github.com:florisvb/PyNumDiff into improve-fd
2 parents 61a9e65 + f14af42 commit 61a1be5

3 files changed

Lines changed: 121 additions & 177 deletions

File tree

pynumdiff/utils/_pi_cruise_control.py

Lines changed: 0 additions & 65 deletions
This file was deleted.

pynumdiff/utils/old_pi_cruise_control.py

Lines changed: 55 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
"""
2-
Simulation and Control of a cruise ?
3-
"""
4-
1+
"""Simulation and Control of cruise control, in all its nonlinear glory"""
52
import numpy as np
63
from pynumdiff.utils import utility
74

@@ -21,18 +18,12 @@
2118

2219

2320
def triangle(iterations, dt):
24-
"""
25-
Create sawtooth pattern of hills for the car to drive over.
26-
27-
:param iterations: number of time points in time series
28-
:type iterations: int
21+
"""Create sawtooth pattern of hills for the car to drive over.
2922
30-
:param dt: time step in seconds
31-
:type dt: float
32-
33-
:return: time series of hills (angle of road as a function of time)
34-
:rtype: np.matrix
23+
:param int iterations: number of time points in time series
24+
:param float dt: time step in seconds
3525
26+
:return: (np.array) -- time series of hills (angle of road as a function of time)
3627
"""
3728
t = np.arange(0, iterations*dt, dt)
3829
continuous_x = np.sin(0.02*t*np.sqrt(t))
@@ -59,34 +50,25 @@ def triangle(iterations, dt):
5950
reversal_vals = np.array(reversal_vals)[idx]
6051
reversal_ts = t[reversal_idxs]
6152

62-
x = np.interp(t, reversal_ts, reversal_vals)
63-
x = np.matrix(x)
64-
65-
return x
53+
return np.interp(t, reversal_ts, reversal_vals)
6654

6755

6856
def effective_wheel_radius(v=20):
69-
"""
70-
Allow effective wheel radius to be a function of velocity.
57+
"""Allow effective wheel radius to be a function of velocity.
7158
72-
:param v: ignored for now
73-
:type v:
59+
:param float v: velocity
7460
75-
:return: effective wheel radius, constant for now
76-
:rtype: float
61+
:return: (float) -- effective wheel radius, constant for now
7762
"""
7863
return v
7964

8065

8166
def torque(omega):
82-
"""
83-
Convert throttle input to Torque. See Astrom and Murray 2008 Chapter 3.
67+
"""Convert throttle input to Torque. See Astrom and Murray 2008 Chapter 3.
8468
85-
:param omega: throttle
86-
:type omega: float
69+
:param float omega: throttle
8770
88-
:return: motor torque
89-
:rtype: float
71+
:return: **torque** (float) -- motor torque
9072
"""
9173
omega_m = parameters['omega_m']
9274
t_m = parameters['T_m']
@@ -96,25 +78,17 @@ def torque(omega):
9678

9779
# pylint: disable-msg=too-many-locals
9880
def step_forward(state_vals, disturbances, desired_v, dt):
99-
"""
100-
One-step Euler integrator that takes the current state, disturbances, and desired velocity and calculates the subsequent state.
101-
102-
:param state_vals: current state [position, velocity, road_angle]
103-
:type state_vals: np.matrix
104-
105-
:param disturbances: current hill angle
106-
:type disturbances: np.matrix
107-
108-
:param desired_velocity: current desired velocity
109-
:type desired_velocity: np.matrix
81+
"""One-step Euler integrator that takes the current state, disturbances, and
82+
desired velocity and calculates the subsequent state.
11083
111-
:param dt: time step (seconds)
112-
:type dt: float
84+
:param np.array state_vals: current state [position, velocity, road_angle]
85+
:param np.array disturbances: current hill angle
86+
:param np.array desired_v: current desired velocity
87+
:param float dt: time step (seconds)
11388
114-
:return: a tuple consisting of:
115-
- new_state: new state
116-
- u: control inputs
117-
:rtype: tuple -> (np.matrix, np.matrix)
89+
:return: tuple[np.array, np.array] of\n
90+
- **new_state** -- new state
91+
- **u** -- control inputs
11892
"""
11993
p = state_vals[0, -1]
12094
v = state_vals[1, -1]
@@ -125,9 +99,9 @@ def step_forward(state_vals, disturbances, desired_v, dt):
12599
rho = parameters['rho']
126100
Cd = parameters['Cd']
127101
A = parameters['A']
128-
v_r = desired_v[0, -1]
102+
v_r = desired_v[-1]
129103
alpha_n = effective_wheel_radius(v)
130-
z = np.sum(desired_v[0, :] - state_vals[1, :])*dt
104+
z = np.sum(desired_v - state_vals[1, :])*dt
131105
k_p = parameters['k_p']
132106
k_i = parameters['k_i']
133107
u = k_p*(v_r-v) + k_i*z
@@ -141,87 +115,63 @@ def step_forward(state_vals, disturbances, desired_v, dt):
141115
# driving force
142116
Fd = alpha_n*u*torque(alpha_n*v)
143117
vdot = 1/m*(Fd - (Fr + Fa + Fg))
144-
new_state = np.matrix([[p + dt*v], [v + vdot*dt], [theta]])
145-
return new_state, np.matrix(u)
118+
new_state = np.array([[p + dt*v], [v + vdot*dt], [theta]])
119+
return new_state, u
146120

147121

148122
# disturbance
149123
def hills(iterations, dt, factor):
150-
"""
151-
Wrapper for creating a hill profile for the car to drive over that has an appropriate length and magnitude
152-
153-
:param iterations: number of time points to simulate
154-
:type iterations: int
155-
156-
:param dt: timestep of simulation in seconds
157-
:type dt: float
124+
"""Wrapper for creating a hill profile for the car to drive over that has an appropriate length and magnitude
158125
159-
:param factor: determines magnitude of the hills
160-
:type factor: int
126+
:param int iterations: number of time points to simulate
127+
:param float dt: timestep of simulation in seconds
128+
:param int factor: determines magnitude of the hills
161129
162-
163-
:return: hills, the output of the triangle function, a [1,M] matrix where M is the number of time points simulated
164-
:rtype: np.matrix
130+
:return: **hills** (np.array) -- the output of the triangle function, a shape (M,) array where M is the number
131+
of time points simulated
165132
"""
166133
return triangle(iterations, dt)*0.3/factor
167134

168135

169136
# desired velocity
170137
def desired_velocity(n, factor):
171-
"""
172-
Wrapper for defining the desired velocity as a matrix with size [1, M], where M is the number of time points to simulate
173-
See function "run" for how this function gets used.
174-
175-
:param n: number of time points to simulate
176-
:type n: int
138+
"""Wrapper for defining the desired velocity as an array of shape (M,), where M is the number of time points
139+
to simulate.
177140
178-
:param factor: factor that determines the magnitude of the desired velocity
179-
:type factor: float
141+
:param int n: number of time points to simulate
142+
:param float factor: factor that determines the magnitude of the desired velocity
180143
181-
:return: desired velocity as function of time, a [1,M] matrix, M is the number of time points to simulate
182-
:rtype: np.matrix
144+
:return: (np.array) -- desired velocity as function of time
183145
"""
184-
return np.matrix([2/factor]*n)
146+
return np.array([2/factor]*n)
185147

186148

187-
def run(timeseries_length=4, dt=0.01):
188-
"""
189-
Simulate proportional integral control of a car attempting to maintain constant velocity while going up and down hills.
190-
This function is used for testing differentiation methods.
191-
192-
See Astrom and Murray 2008 Chapter 3.
193-
194-
:param timeseries_length: number of seconds to simulate
195-
:type timeseries_length: float
149+
def run(duration=4, dt=0.01):
150+
"""Simulate proportional integral control of a car attempting to maintain constant velocity while going up
151+
and down hills. This function can be used for testing differentiation methods. See Astrom and Murray 2008
152+
Chapter 3.
196153
197-
:param dt: timestep in seconds
198-
:type dt: float
154+
:param float duration: number of seconds to simulate
155+
:param float dt: timestep in seconds
199156
200-
:return: a tuple consisting of arrays of size [N, M], where M is the number of time steps.:
201-
- state_vals: state of the car, i.e. position and velocity as a function of time
202-
- disturbances: disturbances, ie. hills, that the car is subjected to
203-
- controls: control inputs applied by the car
204-
:rtype: tuple -> (np.array, np.array, np.array)
157+
:return: tuple[np.array, np.array, np.array] of\n
158+
- **state_vals** -- state of the car, i.e. position and velocity as a function of time, shape (N,M)
159+
- **disturbances** -- disturbances from hills that the car is subjected to, shape (M,)
160+
- **controls** -- control inputs applied by the car, shape (M+1,)
205161
"""
206-
t = np.arange(0, timeseries_length, dt)
162+
t = np.arange(0, duration, dt)
207163
iterations = len(t)
208164

209-
# hills
210-
disturbances = np.matrix(np.zeros([3, iterations+1]))
211-
h = hills(iterations+1, dt, factor=0.5*timeseries_length/2)
212-
disturbances[2, :] = h[:, 0:disturbances.shape[1]]
213-
214-
# controls
215-
controls = np.matrix([[0]])
216-
217-
# initial condition
218-
state_vals = np.matrix([[0], [0], [0]])
165+
disturbances = np.array(np.zeros([3, iterations+1])) # disturbance from hills
166+
h = hills(iterations+1, dt, factor=0.5*duration/2)
167+
disturbances[2, :] = h[0:disturbances.shape[1]]
219168

220-
# desired vel
221-
v_r = desired_velocity(iterations, factor=0.5*iterations*dt/2)
169+
controls = np.array([0])
170+
state_vals = np.array([[0], [0], [0]]) # initial condition
171+
v_r = desired_velocity(iterations, factor=0.5*iterations*dt/2) # desired, reference velocity
222172

223173
for i in range(1, iterations+1):
224-
new_state, u = step_forward(state_vals, disturbances[:, 0:i], v_r[:, 0:i], dt)
174+
new_state, u = step_forward(state_vals, disturbances[:, 0:i], v_r[0:i], dt)
225175
state_vals = np.hstack((state_vals, new_state))
226176
controls = np.hstack((controls, u))
227177

0 commit comments

Comments
 (0)