-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsteering.py
67 lines (56 loc) · 2.4 KB
/
steering.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
import numpy as np
import control as ct
# Define the nonlinear dynamics for the vehicle steering system
def steering_update(t, x, u, params):
"""
Nonlinear dynamics of the vehicle steering system.
Parameters:
t : float
Current time (not used in the dynamics, but included for compatibility).
x : array_like
Current state vector: [x1, x2, x3].
u : array_like
Input vector: [velocity, steering angle].
params : dict
Dictionary of parameters (a, b, maxsteer).
Returns:
dx : array_like
State derivatives: [dx1, dx2, dx3].
"""
a = params.get('a', 1.5) # Offset to vehicle reference point [m]
b = params.get('b', 3.0) # Vehicle wheelbase [m]
maxsteer = params.get('maxsteer', 0.5) # Max steering angle [rad]
# Saturate the steering input
delta = np.clip(u[1], -maxsteer, maxsteer)
# System dynamics
alpha = np.arctan2(a * np.tan(delta), b)
dx1 = u[0] * np.cos(x[2] + alpha) # x velocity
dx2 = u[0] * np.sin(x[2] + alpha) # y velocity
dx3 = (u[0] / b) * np.tan(delta) # Angular velocity
return [dx1, dx2, dx3]
# Create a nonlinear input/output system
steering = ct.nlsys(
steering_update, # Update function for system dynamics
inputs=['v', 'delta'], # Inputs: velocity and steering angle
outputs=None, # Outputs are the same as the states
states=['x', 'y', 'theta'], # States: x, y, and theta (angle)
name='steering',
params={'a': 1.5, 'b': 3.0, 'maxsteer': 0.5} # Default parameters
)
# Generate the linearization at a given velocity
def linearize_lateral(v0=10, normalize=False, output_full_state=False):
# Compute the linearization at the given velocity
linsys = ct.linearize(steering, 0, [v0, 0])[1, 1]
# Extract out the lateral dynamics
latsys = ct.model_reduction(
linsys, [0], method='truncate', warn_unstable=False)
# Normalize coordinates if desired
if normalize:
b = steering.params['b']
latsys = ct.similarity_transform(
latsys, np.array([[1/b, 0], [0, 1]]), timescale=v0/b)
C = np.eye(2) if output_full_state else np.array([[1, 0]])
# Normalized system with (normalized) lateral offset as output
return ct.ss(
latsys.A, latsys.B, C, 0, inputs='delta',
outputs=['y', 'theta'] if output_full_state else 'y')