Files
PythonRobotics/AerialNavigation/quad_sim.py
2018-08-26 11:15:13 -04:00

189 lines
4.9 KiB
Python

"""
Simulate a quadrotor following a 3D trajectory
Author: Daniel Ingram (daniel-s-ingram)
"""
from math import cos, sin
import numpy as np
from Quadrotor import Quadrotor
from TrajectoryGenerator import TrajectoryGenerator
#Simulation parameters
g = 9.81
m = 0.2
Ixx = 1
Iyy = 1
Izz = 1
T = 5
#Proportional coefficients
Kp_x = 1
Kp_y = 1
Kp_z = 1
Kp_roll = 25
Kp_pitch = 25
Kp_yaw = 25
#Derivative coefficients
Kd_x = 10
Kd_y = 10
Kd_z = 1
def quad_sim(x_c, y_c, z_c):
"""
Calculates the necessary thrust and torques for the quadrotor to
follow the trajectory described by the sets of coefficients
x_c, y_c, and z_c.
"""
x_pos = -5
y_pos = -5
z_pos = 5
x_vel = 0
y_vel = 0
z_vel = 0
x_acc = 0
y_acc = 0
z_acc = 0
roll = 0
pitch = 0
yaw = 0
roll_vel = 0
pitch_vel = 0
yaw_vel = 0
des_yaw = 0
dt = 0.1
t = 0
q = Quadrotor(x=x_pos, y=y_pos, z=z_pos, roll=roll, pitch=pitch, yaw=yaw, size=1)
i = 0
while True:
while t <= T:
des_x_pos = calculate_position(x_c[i], t)
des_y_pos = calculate_position(y_c[i], t)
des_z_pos = calculate_position(z_c[i], t)
des_x_vel = calculate_velocity(x_c[i], t)
des_y_vel = calculate_velocity(y_c[i], t)
des_z_vel = calculate_velocity(z_c[i], t)
des_x_acc = calculate_acceleration(x_c[i], t)
des_y_acc = calculate_acceleration(y_c[i], t)
des_z_acc = calculate_acceleration(z_c[i], t)
thrust = m*(g + des_z_acc + Kp_z*(des_z_pos - z_pos) + Kd_z*(des_z_vel - z_vel))
roll_torque = Kp_roll*(((des_x_acc*sin(des_yaw) - des_y_acc*cos(des_yaw))/g) - roll)
pitch_torque = Kp_pitch*(((des_x_acc*cos(des_yaw) - des_y_acc*sin(des_yaw))/g) - pitch)
yaw_torque = Kp_yaw*(des_yaw - yaw)
roll_vel += roll_torque*dt/Ixx
pitch_vel += pitch_torque*dt/Iyy
yaw_vel += yaw_torque*dt/Izz
roll += roll_vel*dt
pitch += pitch_vel*dt
yaw += yaw_vel*dt
R = rotation_matrix(roll, pitch, yaw)
acc = (np.matmul(R, np.array([0, 0, thrust]).T) - np.array([0, 0, m*g]).T)/m
x_acc = acc[0]
y_acc = acc[1]
z_acc = acc[2]
x_vel += x_acc*dt
y_vel += y_acc*dt
z_vel += z_acc*dt
x_pos += x_vel*dt
y_pos += y_vel*dt
z_pos += z_vel*dt
q.update_pose(x_pos, y_pos, z_pos, roll, pitch, yaw)
t += dt
t = 0
i = (i+1)%4
def calculate_position(c, t):
"""
Calculates a position given a set of quintic coefficients and a time.
Args
c: List of coefficients generated by a quintic polynomial
trajectory generator.
t: Time at which to calculate the position
Returns
Position
"""
return c[0]*t**5 + c[1]*t**4 + c[2]*t**3 + c[3]*t**2 + c[4]*t + c[5]
def calculate_velocity(c, t):
"""
Calculates a velocity given a set of quintic coefficients and a time.
Args
c: List of coefficients generated by a quintic polynomial
trajectory generator.
t: Time at which to calculate the velocity
Returns
Velocity
"""
return 5*c[0]*t**4 + 4*c[1]*t**3 + 3*c[2]*t**2 + 2*c[3]*t + c[4]
def calculate_acceleration(c, t):
"""
Calculates an acceleration given a set of quintic coefficients and a time.
Args
c: List of coefficients generated by a quintic polynomial
trajectory generator.
t: Time at which to calculate the acceleration
Returns
Acceleration
"""
return 20*c[0]*t**3 + 12*c[1]*t**2 + 6*c[2]*t + 2*c[3]
def rotation_matrix(roll, pitch, yaw):
"""
Calculates the ZYX rotation matrix.
Args
Roll: Angular position about the x-axis in radians.
Pitch: Angular position about the y-axis in radians.
Yaw: Angular position about the z-axis in radians.
Returns
3x3 rotation matrix as NumPy array
"""
return np.array(
[[cos(yaw)*cos(pitch), -sin(yaw)*cos(roll)+cos(yaw)*sin(pitch)*sin(roll), sin(yaw)*sin(roll)+cos(yaw)*sin(pitch)*cos(roll)],
[sin(yaw)*cos(pitch), cos(yaw)*cos(roll)+sin(yaw)*sin(pitch)*sin(roll), -cos(yaw)*sin(roll)+sin(yaw)*sin(pitch)*cos(roll)],
[-sin(pitch), cos(pitch)*sin(roll), cos(pitch)*cos(yaw)]
])
def main():
"""
Calculates the x, y, z coefficients for the four segments
of the trajectory
"""
x_coeffs = [[], [], [], []]
y_coeffs = [[], [], [], []]
z_coeffs = [[], [], [], []]
waypoints = [[-5, -5, 5], [5, -5, 5], [5, 5, 5], [-5, 5, 5]]
for i in range(4):
traj = TrajectoryGenerator(waypoints[i], waypoints[(i+1)%4], T)
traj.solve()
x_coeffs[i] = traj.x_c
y_coeffs[i] = traj.y_c
z_coeffs[i] = traj.z_c
quad_sim(x_coeffs, y_coeffs, z_coeffs)
if __name__ == "__main__":
main()