-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflight_ctrl_sim.py
197 lines (132 loc) · 5.04 KB
/
flight_ctrl_sim.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import numpy as np
import matplotlib.pyplot as plt
from numpy import sqrt
TAU = 2. * np.pi
N = 50_000 * 10
# DT = 1. / 6_666.666 # todo
DT = 1./10.
# this many sim ticks per DT.
SIM_RATIO = 100
ctrl_effectiveness = 1
p_ω = 0.30
time_to_correction_p_ω = 0.2
time_to_correction_p_θ = 0.5
max_ω_dot = 10.
drag_coeff_ctrls = 0.01
# The change we need to effect given the initial conditions below.
θ_target = 10.
θ = np.zeros(N)
ω = np.zeros(N)
ω_dot = np.zeros(N)
θ[0] = 1
ω[0] = 1
# ω_dot[0] = -1
θ[1] = 1
ω[1] = 0
# ω_dot[1] = -1
drag_coeff_sim = 0.01
# omega_dot_dot_held = 0
def run():
ω_dot_commanded = -1
for i in range(2, N-2):
ω[i-1] = ω[i-2] + ω_dot_commanded * DT / SIM_RATIO
# Subtract, due to how this sim is set up re delta theta.
θ[i] = θ[i-1] - ω[i-1] * DT / SIM_RATIO
if i % SIM_RATIO == 0:
ω_dot_meas = ω[i-1] - ω[i-2]
EPS = 0.00001
if abs(ω_dot_meas) < EPS:
t = -(3 * θ[i]) / (2. * ω[i])
else:
inner = 4. * ω[i]**2 - 6. * ω_dot_meas * θ[i]
if abs(inner) < EPS:
pass
# todo...
else:
t_a = -(np.sqrt(inner) + 2. * ω[i]) / ω_dot_meas
t_b = (np.sqrt(inner) - 2. * ω[i]) / ω_dot_meas
if t_a < 0:
t = t_b
else:
t = t_a
ω_dot_dot = 6. * (2. * θ[i] + t * ω[i]) / t**3
ω_dot_commanded = ω_dot_meas + ω_dot_dot
# todo: More sophisticated integration method.
# ω[i] = ω[i-1] + ω_dot[i-1] * DT / SIM_RATIO
# todo: Incorporate drag in sim and control code
plt.plot(θ)
plt.show()
plt.plot(ω)
plt.show()
plt.plot(ω_dot)
plt.show()
def plot_analytic():
# for θ_0 in [0.5, 1.]:
# for ω_0 in [0., 1., 2.]:
for θ_0 in [4]:
for ω_0 in [-2]:
# time to correct
# t = θ_0 + ω_0
# Alternatively, specify initial angular accel
ω_dot_0 = -2.
EPS = 0.00001
# An alternative approach where we specify initial
# acceleration. This has the advantage of being clearly
# specified by measured params (theta, omega, omega_dot)
# todo: You have 2 edge cases, which require deviating from the
# todo linear correction #1: inner < 0. (no linear jerk solution from current
# accel) #2. ttc too higgh. We fix both by modifying the acceleration
# discontinuously.
# todo: Set a max ttc per theta.
t = 0
if abs(ω_dot_0) < EPS:
t = -(3 * θ_0) / (2. * ω_0)
print("c")
else:
inner = 4. * ω_0**2 - 6. * ω_dot_0 * θ_0
if inner < 0.:
print("Unable to find solution")
t = 6.9 # todo: Option in Rust
else:
t_a = (np.sqrt(inner) + 2. * ω_0) / -ω_dot_0
t_b = (np.sqrt(inner) - 2. * ω_0) / ω_dot_0
print(f"TA: {t_a}, TB: {t_b}")
if t_a < 0:
t = t_b
print("b")
else:
t = t_a
print("a")
if abs(t - 6.9) < EPS:
pass
# Set TTC; use our old method
# todo: Which t? a or b may result in negative time; that's a clue
ω_dot_dot = 6. * (2.*θ_0 + t*ω_0) / t**3
print(f"\n\n ω_dot_0: {ω_dot_0}, ω_dot_dot: {ω_dot_dot}, ttc: {t}")
n = 30_000
dt = 1e-4
θ = np.zeros(n)
ω = np.zeros(n)
ω_dot = np.zeros(n)
# This acceleration integral represents our "delta V" - it's a measure
# of how much correction energy is needed. Its somewhat analagous to impulse.
# it may be an analog of ttc.
# ω_dot_integral = 0
# ω_dot_integral_over_t = np.zeros(N)
for i in range(n):
t_ = i * dt
θ[i] = θ_0 + ω_0 * t_ + 1/2 * ω_dot_0 * t_**2 + \
1/6 * ω_dot_dot * t_**3
ω[i] = ω_0 + ω_dot_0 * t_ + 1/2 * ω_dot_dot * t_**2
ω_dot[i] = ω_dot_0 + ω_dot_dot * t_
# ω_dot_integral += abs(ω_dot[i])
# ω_dot_integral_over_t[i] = ω_dot_integral
# GUess: omega goes with square, theta goes with cube?
plt.plot(θ)
plt.plot(ω)
plt.plot(ω_dot)
plt.show()
plot_analytic()
# run()
# some data (theta0, omega0 = 1, 1)
# t=1: theta = 0.625, omega = -1.75