1
+ """
2
+ Simulate a quadrotor following a 3D trajectory
3
+
4
+ Author: Daniel Ingram (daniel-s-ingram)
5
+ """
6
+
7
+ from math import cos , sin
8
+ import numpy as np
9
+ from Quadrotor import Quadrotor
10
+ from TrajectoryGenerator import TrajectoryGenerator
11
+
12
+ #Simulation parameters
13
+ g = 9.81
14
+ m = 0.2
15
+ Ixx = 1
16
+ Iyy = 1
17
+ Izz = 1
18
+ T = 5
19
+
20
+ #Proportional coefficients
21
+ Kp_x = 1
22
+ Kp_y = 1
23
+ Kp_z = 1
24
+ Kp_roll = 25
25
+ Kp_pitch = 25
26
+ Kp_yaw = 25
27
+
28
+ #Derivative coefficients
29
+ Kd_x = 10
30
+ Kd_y = 10
31
+ Kd_z = 1
32
+
33
+ def quad_sim (x_c , y_c , z_c ):
34
+ """
35
+ Calculates the necessary thrust and torques for the quadrotor to
36
+ follow the trajectory described by the sets of coefficients
37
+ x_c, y_c, and z_c.
38
+ """
39
+ x_pos = - 5
40
+ y_pos = - 5
41
+ z_pos = 5
42
+ x_vel = 0
43
+ y_vel = 0
44
+ z_vel = 0
45
+ x_acc = 0
46
+ y_acc = 0
47
+ z_acc = 0
48
+ roll = 0
49
+ pitch = 0
50
+ yaw = 0
51
+ roll_vel = 0
52
+ pitch_vel = 0
53
+ yaw_vel = 0
54
+
55
+ des_yaw = 0
56
+
57
+ dt = 0.1
58
+ t = 0
59
+
60
+ q = Quadrotor (x = x_pos , y = y_pos , z = z_pos , roll = roll , pitch = pitch , yaw = yaw , size = 1 )
61
+
62
+ i = 0
63
+
64
+ while True :
65
+ while t <= T :
66
+ des_x_pos = calculate_position (x_c [i ], t )
67
+ des_y_pos = calculate_position (y_c [i ], t )
68
+ des_z_pos = calculate_position (z_c [i ], t )
69
+ des_x_vel = calculate_velocity (x_c [i ], t )
70
+ des_y_vel = calculate_velocity (y_c [i ], t )
71
+ des_z_vel = calculate_velocity (z_c [i ], t )
72
+ des_x_acc = calculate_acceleration (x_c [i ], t )
73
+ des_y_acc = calculate_acceleration (y_c [i ], t )
74
+ des_z_acc = calculate_acceleration (z_c [i ], t )
75
+
76
+ thrust = m * (g + des_z_acc + Kp_z * (des_z_pos - z_pos ) + Kd_z * (des_z_vel - z_vel ))
77
+
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 )
81
+
82
+ roll_vel += roll_torque * dt / Ixx
83
+ pitch_vel += pitch_torque * dt / Iyy
84
+ yaw_vel += yaw_torque * dt / Izz
85
+
86
+ roll += roll_vel * dt
87
+ pitch += pitch_vel * dt
88
+ yaw += yaw_vel * dt
89
+
90
+ 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
92
+ x_acc = acc [0 ]
93
+ y_acc = acc [1 ]
94
+ 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
101
+
102
+ q .update_pose (x_pos , y_pos , z_pos , roll , pitch , yaw )
103
+
104
+ t += dt
105
+
106
+ t = 0
107
+ i = (i + 1 )% 4
108
+
109
+ def calculate_position (c , t ):
110
+ """
111
+ Calculates a position given a set of quintic coefficients and a time.
112
+
113
+ Args
114
+ c: List of coefficients generated by a quintic polynomial
115
+ trajectory generator.
116
+ t: Time at which to calculate the position
117
+
118
+ Returns
119
+ Position
120
+ """
121
+ return c [0 ]* t ** 5 + c [1 ]* t ** 4 + c [2 ]* t ** 3 + c [3 ]* t ** 2 + c [4 ]* t + c [5 ]
122
+
123
+ def calculate_velocity (c , t ):
124
+ """
125
+ Calculates a velocity given a set of quintic coefficients and a time.
126
+
127
+ Args
128
+ c: List of coefficients generated by a quintic polynomial
129
+ trajectory generator.
130
+ t: Time at which to calculate the velocity
131
+
132
+ Returns
133
+ Velocity
134
+ """
135
+ return 5 * c [0 ]* t ** 4 + 4 * c [1 ]* t ** 3 + 3 * c [2 ]* t ** 2 + 2 * c [3 ]* t + c [4 ]
136
+
137
+ def calculate_acceleration (c , t ):
138
+ """
139
+ Calculates an acceleration given a set of quintic coefficients and a time.
140
+
141
+ Args
142
+ c: List of coefficients generated by a quintic polynomial
143
+ trajectory generator.
144
+ t: Time at which to calculate the acceleration
145
+
146
+ Returns
147
+ Acceleration
148
+ """
149
+ return 20 * c [0 ]* t ** 3 + 12 * c [1 ]* t ** 2 + 6 * c [2 ]* t + 2 * c [3 ]
150
+
151
+ def rotation_matrix (roll , pitch , yaw ):
152
+ """
153
+ Calculates the ZYX rotation matrix.
154
+
155
+ Args
156
+ Roll: Angular position about the x-axis in radians.
157
+ Pitch: Angular position about the y-axis in radians.
158
+ Yaw: Angular position about the z-axis in radians.
159
+
160
+ Returns
161
+ 3x3 rotation matrix as NumPy array
162
+ """
163
+ 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
+ ])
168
+
169
+ def main ():
170
+ """
171
+ Calculates the x, y, z coefficients for the four segments
172
+ of the trajectory
173
+ """
174
+ x_coeffs = [[], [], [], []]
175
+ y_coeffs = [[], [], [], []]
176
+ z_coeffs = [[], [], [], []]
177
+ waypoints = [[- 5 , - 5 , 5 ], [5 , - 5 , 5 ], [5 , 5 , 5 ], [- 5 , 5 , 5 ]]
178
+
179
+ for i in range (4 ):
180
+ traj = TrajectoryGenerator (waypoints [i ], waypoints [(i + 1 )% 4 ], T )
181
+ traj .solve ()
182
+ x_coeffs [i ] = traj .x_c
183
+ y_coeffs [i ] = traj .y_c
184
+ z_coeffs [i ] = traj .z_c
185
+
186
+ quad_sim (x_coeffs , y_coeffs , z_coeffs )
187
+
188
+ if __name__ == "__main__" :
189
+ main ()
0 commit comments