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