Skip to content

Commit 907c464

Browse files
committed
add Quadrotor animation
1 parent 833f93c commit 907c464

File tree

4 files changed

+65
-42
lines changed

4 files changed

+65
-42
lines changed

AerialNavigation/Quadrotor.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import matplotlib.pyplot as plt
1010
from mpl_toolkits.mplot3d import Axes3D
1111

12+
1213
class Quadrotor():
1314
def __init__(self, x=0, y=0, z=0, roll=0, pitch=0, yaw=0, size=0.25):
14-
self.p1 = np.array([size/2, 0, 0, 1]).T
15-
self.p2 = np.array([-size/2, 0, 0, 1]).T
16-
self.p3 = np.array([0, size/2, 0, 1]).T
17-
self.p4 = np.array([0, -size/2, 0, 1]).T
15+
self.p1 = np.array([size / 2, 0, 0, 1]).T
16+
self.p2 = np.array([-size / 2, 0, 0, 1]).T
17+
self.p3 = np.array([0, size / 2, 0, 1]).T
18+
self.p4 = np.array([0, -size / 2, 0, 1]).T
1819

1920
self.x_data = []
2021
self.y_data = []
@@ -47,10 +48,11 @@ def transformation_matrix(self):
4748
pitch = self.pitch
4849
yaw = self.yaw
4950
return np.array(
50-
[[cos(yaw)*cos(pitch), -sin(yaw)*cos(roll)+cos(yaw)*sin(pitch)*sin(roll), sin(yaw)*sin(roll)+cos(yaw)*sin(pitch)*cos(roll), x],
51-
[sin(yaw)*cos(pitch), cos(yaw)*cos(roll)+sin(yaw)*sin(pitch)*sin(roll), -cos(yaw)*sin(roll)+sin(yaw)*sin(pitch)*cos(roll), y],
52-
[-sin(pitch), cos(pitch)*sin(roll), cos(pitch)*cos(yaw), z]
53-
])
51+
[[cos(yaw) * cos(pitch), -sin(yaw) * cos(roll) + cos(yaw) * sin(pitch) * sin(roll), sin(yaw) * sin(roll) + cos(yaw) * sin(pitch) * cos(roll), x],
52+
[sin(yaw) * cos(pitch), cos(yaw) * cos(roll) + sin(yaw) * sin(pitch) *
53+
sin(roll), -cos(yaw) * sin(roll) + sin(yaw) * sin(pitch) * cos(roll), y],
54+
[-sin(pitch), cos(pitch) * sin(roll), cos(pitch) * cos(yaw), z]
55+
])
5456

5557
def plot(self):
5658
T = self.transformation_matrix()
@@ -66,14 +68,15 @@ def plot(self):
6668
[p1_t[1], p2_t[1], p3_t[1], p4_t[1]],
6769
[p1_t[2], p2_t[2], p3_t[2], p4_t[2]], 'k.')
6870

69-
self.ax.plot([p1_t[0], p2_t[0]], [p1_t[1], p2_t[1]], [p1_t[2], p2_t[2]], 'r-')
70-
self.ax.plot([p3_t[0], p4_t[0]], [p3_t[1], p4_t[1]], [p3_t[2], p4_t[2]], 'r-')
71+
self.ax.plot([p1_t[0], p2_t[0]], [p1_t[1], p2_t[1]],
72+
[p1_t[2], p2_t[2]], 'r-')
73+
self.ax.plot([p3_t[0], p4_t[0]], [p3_t[1], p4_t[1]],
74+
[p3_t[2], p4_t[2]], 'r-')
7175

7276
self.ax.plot(self.x_data, self.y_data, self.z_data, 'b:')
7377

7478
plt.xlim(-5, 5)
7579
plt.ylim(-5, 5)
7680
self.ax.set_zlim(0, 10)
7781

78-
plt.show()
7982
plt.pause(0.001)

AerialNavigation/animation.gif

10.7 MB
Loading

AerialNavigation/quad_sim.py

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,28 @@
99
from Quadrotor import Quadrotor
1010
from TrajectoryGenerator import TrajectoryGenerator
1111

12-
#Simulation parameters
12+
# Simulation parameters
1313
g = 9.81
1414
m = 0.2
1515
Ixx = 1
1616
Iyy = 1
1717
Izz = 1
1818
T = 5
1919

20-
#Proportional coefficients
20+
# Proportional coefficients
2121
Kp_x = 1
2222
Kp_y = 1
2323
Kp_z = 1
2424
Kp_roll = 25
2525
Kp_pitch = 25
2626
Kp_yaw = 25
2727

28-
#Derivative coefficients
28+
# Derivative coefficients
2929
Kd_x = 10
3030
Kd_y = 10
3131
Kd_z = 1
3232

33+
3334
def quad_sim(x_c, y_c, z_c):
3435
"""
3536
Calculates the necessary thrust and torques for the quadrotor to
@@ -57,9 +58,12 @@ def quad_sim(x_c, y_c, z_c):
5758
dt = 0.1
5859
t = 0
5960

60-
q = Quadrotor(x=x_pos, y=y_pos, z=z_pos, roll=roll, pitch=pitch, yaw=yaw, size=1)
61+
q = Quadrotor(x=x_pos, y=y_pos, z=z_pos, roll=roll,
62+
pitch=pitch, yaw=yaw, size=1)
6163

6264
i = 0
65+
n_run = 8
66+
irun = 0
6367

6468
while True:
6569
while t <= T:
@@ -73,38 +77,48 @@ def quad_sim(x_c, y_c, z_c):
7377
des_y_acc = calculate_acceleration(y_c[i], t)
7478
des_z_acc = calculate_acceleration(z_c[i], t)
7579

76-
thrust = m*(g + des_z_acc + Kp_z*(des_z_pos - z_pos) + Kd_z*(des_z_vel - z_vel))
80+
thrust = m * (g + des_z_acc + Kp_z * (des_z_pos -
81+
z_pos) + Kd_z * (des_z_vel - z_vel))
7782

78-
roll_torque = Kp_roll*(((des_x_acc*sin(des_yaw) - des_y_acc*cos(des_yaw))/g) - roll)
79-
pitch_torque = Kp_pitch*(((des_x_acc*cos(des_yaw) - des_y_acc*sin(des_yaw))/g) - pitch)
80-
yaw_torque = Kp_yaw*(des_yaw - yaw)
83+
roll_torque = Kp_roll * \
84+
(((des_x_acc * sin(des_yaw) - des_y_acc * cos(des_yaw)) / g) - roll)
85+
pitch_torque = Kp_pitch * \
86+
(((des_x_acc * cos(des_yaw) - des_y_acc * sin(des_yaw)) / g) - pitch)
87+
yaw_torque = Kp_yaw * (des_yaw - yaw)
8188

82-
roll_vel += roll_torque*dt/Ixx
83-
pitch_vel += pitch_torque*dt/Iyy
84-
yaw_vel += yaw_torque*dt/Izz
89+
roll_vel += roll_torque * dt / Ixx
90+
pitch_vel += pitch_torque * dt / Iyy
91+
yaw_vel += yaw_torque * dt / Izz
8592

86-
roll += roll_vel*dt
87-
pitch += pitch_vel*dt
88-
yaw += yaw_vel*dt
93+
roll += roll_vel * dt
94+
pitch += pitch_vel * dt
95+
yaw += yaw_vel * dt
8996

9097
R = rotation_matrix(roll, pitch, yaw)
91-
acc = (np.matmul(R, np.array([0, 0, thrust]).T) - np.array([0, 0, m*g]).T)/m
98+
acc = (np.matmul(R, np.array(
99+
[0, 0, thrust]).T) - np.array([0, 0, m * g]).T) / m
92100
x_acc = acc[0]
93101
y_acc = acc[1]
94102
z_acc = acc[2]
95-
x_vel += x_acc*dt
96-
y_vel += y_acc*dt
97-
z_vel += z_acc*dt
98-
x_pos += x_vel*dt
99-
y_pos += y_vel*dt
100-
z_pos += z_vel*dt
103+
x_vel += x_acc * dt
104+
y_vel += y_acc * dt
105+
z_vel += z_acc * dt
106+
x_pos += x_vel * dt
107+
y_pos += y_vel * dt
108+
z_pos += z_vel * dt
101109

102110
q.update_pose(x_pos, y_pos, z_pos, roll, pitch, yaw)
103111

104112
t += dt
105113

106114
t = 0
107-
i = (i+1)%4
115+
i = (i + 1) % 4
116+
irun += 1
117+
if irun >= n_run:
118+
break
119+
120+
print("Done")
121+
108122

109123
def calculate_position(c, t):
110124
"""
@@ -118,7 +132,8 @@ def calculate_position(c, t):
118132
Returns
119133
Position
120134
"""
121-
return c[0]*t**5 + c[1]*t**4 + c[2]*t**3 + c[3]*t**2 + c[4]*t + c[5]
135+
return c[0] * t**5 + c[1] * t**4 + c[2] * t**3 + c[3] * t**2 + c[4] * t + c[5]
136+
122137

123138
def calculate_velocity(c, t):
124139
"""
@@ -132,7 +147,8 @@ def calculate_velocity(c, t):
132147
Returns
133148
Velocity
134149
"""
135-
return 5*c[0]*t**4 + 4*c[1]*t**3 + 3*c[2]*t**2 + 2*c[3]*t + c[4]
150+
return 5 * c[0] * t**4 + 4 * c[1] * t**3 + 3 * c[2] * t**2 + 2 * c[3] * t + c[4]
151+
136152

137153
def calculate_acceleration(c, t):
138154
"""
@@ -146,7 +162,8 @@ def calculate_acceleration(c, t):
146162
Returns
147163
Acceleration
148164
"""
149-
return 20*c[0]*t**3 + 12*c[1]*t**2 + 6*c[2]*t + 2*c[3]
165+
return 20 * c[0] * t**3 + 12 * c[1] * t**2 + 6 * c[2] * t + 2 * c[3]
166+
150167

151168
def rotation_matrix(roll, pitch, yaw):
152169
"""
@@ -161,10 +178,12 @@ def rotation_matrix(roll, pitch, yaw):
161178
3x3 rotation matrix as NumPy array
162179
"""
163180
return np.array(
164-
[[cos(yaw)*cos(pitch), -sin(yaw)*cos(roll)+cos(yaw)*sin(pitch)*sin(roll), sin(yaw)*sin(roll)+cos(yaw)*sin(pitch)*cos(roll)],
165-
[sin(yaw)*cos(pitch), cos(yaw)*cos(roll)+sin(yaw)*sin(pitch)*sin(roll), -cos(yaw)*sin(roll)+sin(yaw)*sin(pitch)*cos(roll)],
166-
[-sin(pitch), cos(pitch)*sin(roll), cos(pitch)*cos(yaw)]
167-
])
181+
[[cos(yaw) * cos(pitch), -sin(yaw) * cos(roll) + cos(yaw) * sin(pitch) * sin(roll), sin(yaw) * sin(roll) + cos(yaw) * sin(pitch) * cos(roll)],
182+
[sin(yaw) * cos(pitch), cos(yaw) * cos(roll) + sin(yaw) * sin(pitch) *
183+
sin(roll), -cos(yaw) * sin(roll) + sin(yaw) * sin(pitch) * cos(roll)],
184+
[-sin(pitch), cos(pitch) * sin(roll), cos(pitch) * cos(yaw)]
185+
])
186+
168187

169188
def main():
170189
"""
@@ -177,13 +196,14 @@ def main():
177196
waypoints = [[-5, -5, 5], [5, -5, 5], [5, 5, 5], [-5, 5, 5]]
178197

179198
for i in range(4):
180-
traj = TrajectoryGenerator(waypoints[i], waypoints[(i+1)%4], T)
199+
traj = TrajectoryGenerator(waypoints[i], waypoints[(i + 1) % 4], T)
181200
traj.solve()
182201
x_coeffs[i] = traj.x_c
183202
y_coeffs[i] = traj.y_c
184203
z_coeffs[i] = traj.z_c
185204

186205
quad_sim(x_coeffs, y_coeffs, z_coeffs)
187206

207+
188208
if __name__ == "__main__":
189209
main()

0 commit comments

Comments
 (0)