00001
00002 import numpy as np
00003
00004 def normalize(v):
00005 norm = np.linalg.norm(v)
00006 assert norm > 0
00007 return v / norm
00008
00009
00010 class Polynomial:
00011 def __init__(self, p):
00012 self.p = p
00013
00014
00015 def eval(self, t):
00016 assert t >= 0
00017 x = 0.0
00018 for i in range(0, len(self.p)):
00019 x = x * t + self.p[len(self.p) - 1 - i]
00020 return x
00021
00022
00023 def derivative(self):
00024 return Polynomial([(i+1) * self.p[i+1] for i in range(0, len(self.p) - 1)])
00025
00026
00027 class TrajectoryOutput:
00028 def __init__(self):
00029 self.pos = None
00030 self.vel = None
00031 self.acc = None
00032 self.omega = None
00033 self.yaw = None
00034
00035
00036
00037 class Polynomial4D:
00038 def __init__(self, duration, px, py, pz, pyaw):
00039 self.duration = duration
00040 self.px = Polynomial(px)
00041 self.py = Polynomial(py)
00042 self.pz = Polynomial(pz)
00043 self.pyaw = Polynomial(pyaw)
00044
00045
00046 def derivative(self):
00047 return Polynomial4D(
00048 self.duration,
00049 self.px.derivative().p,
00050 self.py.derivative().p,
00051 self.pz.derivative().p,
00052 self.pyaw.derivative().p)
00053
00054 def eval(self, t):
00055 result = TrajectoryOutput()
00056
00057 result.pos = np.array([self.px.eval(t), self.py.eval(t), self.pz.eval(t)])
00058 result.yaw = self.pyaw.eval(t)
00059
00060
00061 derivative = self.derivative()
00062 result.vel = np.array([derivative.px.eval(t), derivative.py.eval(t), derivative.pz.eval(t)])
00063 dyaw = derivative.pyaw.eval(t)
00064
00065
00066 derivative2 = derivative.derivative()
00067 result.acc = np.array([derivative2.px.eval(t), derivative2.py.eval(t), derivative2.pz.eval(t)])
00068
00069
00070 derivative3 = derivative2.derivative()
00071 jerk = np.array([derivative3.px.eval(t), derivative3.py.eval(t), derivative3.pz.eval(t)])
00072
00073 thrust = result.acc + np.array([0, 0, 9.81])
00074
00075 z_body = normalize(thrust)
00076 x_world = np.array([np.cos(result.yaw), np.sin(result.yaw), 0])
00077 y_body = normalize(np.cross(z_body, x_world))
00078 x_body = np.cross(y_body, z_body)
00079
00080 jerk_orth_zbody = jerk - (np.dot(jerk, z_body) * z_body)
00081 h_w = jerk_orth_zbody / np.linalg.norm(thrust)
00082
00083 result.omega = np.array([-np.dot(h_w, y_body), np.dot(h_w, x_body), z_body[2] * dyaw])
00084 return result
00085
00086
00087 class Trajectory:
00088 def __init__(self):
00089 self.polynomials = None
00090 self.duration = None
00091
00092 def loadcsv(self, filename):
00093 data = np.loadtxt(filename, delimiter=",", skiprows=1, usecols=range(33))
00094 self.polynomials = [Polynomial4D(row[0], row[1:9], row[9:17], row[17:25], row[25:33]) for row in data]
00095 self.duration = np.sum(data[:,0])
00096
00097 def eval(self, t):
00098 assert t >= 0
00099 assert t <= self.duration
00100
00101 current_t = 0.0
00102 for p in self.polynomials:
00103 if t < current_t + p.duration:
00104 return p.eval(t - current_t)
00105 current_t = current_t + p.duration