Skip to content

Commit b0fa82d

Browse files
committed
almost working initial version
1 parent 1d2ad50 commit b0fa82d

File tree

5 files changed

+80
-16
lines changed

5 files changed

+80
-16
lines changed

examples/doubleint.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,26 @@
55
# integrator system. Mainly useful to show the simplest type of trajectory
66
# generation computation.
77

8+
import numpy as np
9+
import matplotlib.pyplot as plt
810
import control as ctrl # control system toolbox
9-
import trajgen as tg # trajectory generation toolbox
11+
import trajgen as tg # trajectory generation toolbox
1012

1113
# Define a double integrator system
1214
sys1 = ctrl.tf2ss(ctrl.tf([1], [1, 0, 0]))
1315

1416
# Set the initial and final conditions
1517
x0 = (0, 0);
16-
xf = (1, 1);
18+
xf = (2, 1);
1719

1820
# Find a trajectory
19-
xd, ud = tg.linear_point_to_point(sys1, x0, xf, 1)
20-
print(xd)
21+
systraj = tg.linear_point_to_point(sys1, x0, xf, 1)
2122

2223
# Plot the trajectory
24+
t = np.linspace(0, 1, 100)
25+
xd, ud = systraj.eval(t)
26+
27+
plt.figure(1); plt.clf()
28+
plt.plot(t, xd[:,0], 'b-', t, xd[:,1], 'g-', t, ud[:,0], 'r--')
29+
plt.legend(('x1', 'x2', 'u'))
30+
plt.show()

trajgen/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Basis function sets
22
from trajgen.poly import Poly
3+
from trajgen.systraj import SystemTrajectory
4+
from trajgen.linflat import LinearFlatSystem
35

46
from flatsys import linear_point_to_point
57

trajgen/flatsys.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import numpy as np
1010
import control
1111
from trajgen import Poly
12+
from trajgen import SystemTrajectory, LinearFlatSystem
1213

1314
# Solve a point to point trajectory generation problem for a linear system
1415
def linear_point_to_point(sys, x0, xf, Tf, basis=None, cost=None, T0 = 0):
@@ -22,6 +23,9 @@ def linear_point_to_point(sys, x0, xf, Tf, basis=None, cost=None, T0 = 0):
2223
raise control.ControlNotImplemented(
2324
"only single input, single output systems are supported")
2425

26+
# Create a flat system representation
27+
system = LinearFlatSystem(sys)
28+
2529
#
2630
# Determine the basis function set to use and make sure it is big enough
2731
#
@@ -33,23 +37,16 @@ def linear_point_to_point(sys, x0, xf, Tf, basis=None, cost=None, T0 = 0):
3337
if (basis.N < 2*sys.states):
3438
raise ValueError("basis set is too small")
3539

36-
#
37-
# Find the transformation to bring the system into reachable form
38-
# and use this to determine the flat output variable z = Cf*x
39-
#
40-
zsys, Tr = control.reachable_form(sys)
41-
Cfz = np.zeros(np.shape(sys.C)); Cfz[-1] = 1
42-
Cfx = Cfz * Tr
43-
4440
#
4541
# Map the initial and final conditions to flat output conditions
4642
#
4743
# We need to compute the output "flag": [z(t), z'(t), z''(t), ...]
4844
# and then evaluate this at the initial and final condition.
4945
#
46+
#! TODO: should be able to represent flag variables as 1D arrays
5047
zflag_T0 = np.zeros((sys.states, 1));
5148
zflag_Tf = np.zeros((sys.states, 1));
52-
H = Cfx # initial state transformation
49+
H = system.C # initial state transformation
5350
for i in range(sys.states):
5451
zflag_T0[i, 0] = H * np.matrix(x0).T
5552
zflag_Tf[i, 0] = H * np.matrix(xf).T
@@ -85,8 +82,11 @@ def linear_point_to_point(sys, x0, xf, Tf, basis=None, cost=None, T0 = 0):
8582
#
8683
# Transform the trajectory from flat outputs to states and inputs
8784
#
88-
xdfcn = alpha
89-
udfcn = lambda t: 0
85+
systraj = SystemTrajectory(sys.states, sys.inputs)
86+
systraj.system = system
87+
systraj.basis = basis
88+
systraj.coeffs = alpha
9089

9190
# Return a function that computes inputs and states as a function of time
92-
return xdfcn, udfcn
91+
return systraj
92+

trajgen/linflat.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
import control
3+
4+
class LinearFlatSystem:
5+
def __init__(self, sys):
6+
self.A = sys.A
7+
self.B = sys.B
8+
9+
# Find the transformation to bring the system into reachable form
10+
zsys, Tr = control.reachable_form(sys)
11+
self.F = zsys.A[0,:] # input function coeffs
12+
self.T = Tr # state space transformation
13+
self.Tinv = np.linalg.inv(Tr) # computer inverse once
14+
15+
# Compute the flat output variable z = C x
16+
Cfz = np.zeros(np.shape(sys.C)); Cfz[-1] = 1
17+
self.C = Cfz * Tr
18+
19+
# Keep track of the number of states and inputs
20+
self.states = sys.states
21+
self.inputs = sys.inputs
22+
23+
# Compute state and input from flat flag
24+
def reverse(self, zflag):
25+
x = self.Tinv * np.matrix(zflag[0:-1]).T
26+
u = zflag[-1] - self.F * x
27+
return np.reshape(x, self.states), np.reshape(u, self.inputs)

trajgen/systraj.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
3+
class SystemTrajectory:
4+
def __init__(self, states, inputs):
5+
self.states = states
6+
self.inputs = inputs
7+
8+
# Evaluate the trajectory over a list of time points
9+
def eval(self, tlist):
10+
# Allocate space for the outputs
11+
xd = np.zeros((len(tlist), self.states))
12+
ud = np.zeros((len(tlist), self.inputs))
13+
14+
# Go through each time point and compute xd and ud via flat variables
15+
for k in range(len(tlist)):
16+
zflag = np.zeros(self.states + self.inputs)
17+
for i in range(self.states + self.inputs):
18+
for j in range(self.basis.N):
19+
#! TODO: rewrite eval_deriv to take in time vector
20+
zflag[i] += self.coeffs[j] * \
21+
self.basis.eval_deriv(j, i, tlist[k])
22+
23+
# Now copy the states and inputs
24+
xd[k,:], ud[k,:] = self.system.reverse(zflag)
25+
26+
return xd, ud
27+

0 commit comments

Comments
 (0)