mirror of
https://github.com/AtsushiSakai/PythonRobotics.git
synced 2026-01-14 07:18:01 -05:00
189 lines
4.9 KiB
Python
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() |