1414import matplotlib .pyplot as plt
1515
1616# NOTE: *_pose is a 3-array: 0 - x coord, 1 - y coord, 2 - orientation angle \theta
17+
18+
1719class eta3_path (object ):
1820 """
1921 eta3_path
2022
2123 input
2224 segments: list of `eta3_path_segment` instances definining a continuous path
2325 """
26+
2427 def __init__ (self , segments ):
2528 # ensure input has the correct form
26- assert (isinstance (segments , list ) and isinstance (segments [0 ], eta3_path_segment ))
29+ assert (isinstance (segments , list ) and isinstance (
30+ segments [0 ], eta3_path_segment ))
2731 # ensure that each segment begins from the previous segment's end (continuity)
28- for r ,s in zip (segments [:- 1 ], segments [1 :]):
32+ for r , s in zip (segments [:- 1 ], segments [1 :]):
2933 assert (np .array_equal (r .end_pose , s .start_pose ))
3034 self .segments = segments
3135 """
@@ -36,10 +40,11 @@ def __init__(self, segments):
3640 returns
3741 2d (x,y) position vector
3842 """
43+
3944 def calc_path_point (self , u ):
4045 assert (u >= 0 and u <= len (self .segments ))
4146 if np .isclose (u , len (self .segments )):
42- segment_idx = len (self .segments )- 1
47+ segment_idx = len (self .segments ) - 1
4348 u = 1.
4449 else :
4550 segment_idx = int (np .floor (u ))
@@ -59,11 +64,12 @@ class eta3_path_segment(object):
5964 eta - shaping parameters, default=None
6065 kappa - curvature parameters, default=None
6166 """
67+
6268 def __init__ (self , start_pose , end_pose , eta = None , kappa = None ):
6369 # make sure inputs are of the correct size
6470 assert (len (start_pose ) == 3 and len (start_pose ) == len (end_pose ))
6571 self .start_pose = start_pose
66- self .end_pose = end_pose
72+ self .end_pose = end_pose
6773 # if no eta is passed, initialize it to array of zeros
6874 if not eta :
6975 eta = np .zeros ((6 ,))
@@ -89,55 +95,68 @@ def __init__(self, start_pose, end_pose, eta=None, kappa=None):
8995 self .coeffs [0 , 1 ] = eta [0 ] * ca
9096 self .coeffs [1 , 1 ] = eta [0 ] * sa
9197 # quadratic (u^2)
92- self .coeffs [0 , 2 ] = 1. / 2 * eta [2 ] * ca - 1. / 2 * eta [0 ]** 2 * kappa [0 ] * sa
93- self .coeffs [1 , 2 ] = 1. / 2 * eta [2 ] * sa + 1. / 2 * eta [0 ]** 2 * kappa [0 ] * ca
98+ self .coeffs [0 , 2 ] = 1. / 2 * eta [2 ] * \
99+ ca - 1. / 2 * eta [0 ]** 2 * kappa [0 ] * sa
100+ self .coeffs [1 , 2 ] = 1. / 2 * eta [2 ] * \
101+ sa + 1. / 2 * eta [0 ]** 2 * kappa [0 ] * ca
94102 # cubic (u^3)
95- self .coeffs [0 , 3 ] = 1. / 6 * eta [4 ] * ca - 1. / 6 * (eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa
96- self .coeffs [1 , 3 ] = 1. / 6 * eta [4 ] * sa + 1. / 6 * (eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca
103+ self .coeffs [0 , 3 ] = 1. / 6 * eta [4 ] * ca - 1. / 6 * \
104+ (eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa
105+ self .coeffs [1 , 3 ] = 1. / 6 * eta [4 ] * sa + 1. / 6 * \
106+ (eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca
97107 # quartic (u^4)
98- self .coeffs [0 , 4 ] = 35. * (end_pose [0 ] - start_pose [0 ]) - (20. * eta [0 ] + 5 * eta [2 ] + 2. / 3 * eta [4 ]) * ca \
99- + (5. * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
100- - (15. * eta [1 ] - 5. / 2 * eta [3 ] + 1. / 6 * eta [5 ]) * cb \
101- - (5. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
102- self .coeffs [1 , 4 ] = 35. * (end_pose [1 ] - start_pose [1 ]) - (20. * eta [0 ] + 5. * eta [2 ] + 2. / 3 * eta [4 ]) * sa \
103- - (5. * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
104- - (15. * eta [1 ] - 5. / 2 * eta [3 ] + 1. / 6 * eta [5 ]) * sb \
105- + (5. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
108+ self .coeffs [0 , 4 ] = 35. * (end_pose [0 ] - start_pose [0 ]) - (20. * eta [0 ] + 5 * eta [2 ] + 2. / 3 * eta [4 ]) * ca \
109+ + (5. * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
110+ - (15. * eta [1 ] - 5. / 2 * eta [3 ] + 1. / 6 * eta [5 ]) * cb \
111+ - (5. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ] **
112+ 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
113+ self .coeffs [1 , 4 ] = 35. * (end_pose [1 ] - start_pose [1 ]) - (20. * eta [0 ] + 5. * eta [2 ] + 2. / 3 * eta [4 ]) * sa \
114+ - (5. * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
115+ - (15. * eta [1 ] - 5. / 2 * eta [3 ] + 1. / 6 * eta [5 ]) * sb \
116+ + (5. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ] **
117+ 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
106118 # quintic (u^5)
107119 self .coeffs [0 , 5 ] = - 84. * (end_pose [0 ] - start_pose [0 ]) + (45. * eta [0 ] + 10. * eta [2 ] + eta [4 ]) * ca \
108120 - (10. * eta [0 ]** 2 * kappa [0 ] + eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
109- + (39. * eta [1 ] - 7. * eta [3 ] + 1. / 2 * eta [5 ]) * cb \
110- + (7. * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
121+ + (39. * eta [1 ] - 7. * eta [3 ] + 1. / 2 * eta [5 ]) * cb \
122+ + (7. * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 *
123+ kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
111124 self .coeffs [1 , 5 ] = - 84. * (end_pose [1 ] - start_pose [1 ]) + (45. * eta [0 ] + 10. * eta [2 ] + eta [4 ]) * sa \
112125 + (10. * eta [0 ]** 2 * kappa [0 ] + eta [0 ]** 3 * kappa [1 ] + 3. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
113- + (39. * eta [1 ] - 7. * eta [3 ] + 1. / 2 * eta [5 ]) * sb \
114- - (7. * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
126+ + (39. * eta [1 ] - 7. * eta [3 ] + 1. / 2 * eta [5 ]) * sb \
127+ - (7. * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 *
128+ kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
115129 # sextic (u^6)
116- self .coeffs [0 , 6 ] = 70. * (end_pose [0 ] - start_pose [0 ]) - (36. * eta [0 ] + 15. / 2 * eta [2 ] + 2. / 3 * eta [4 ]) * ca \
117- + (15. / 2 * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
118- - (34. * eta [1 ] - 13. / 2 * eta [3 ] + 1. / 2 * eta [5 ]) * cb \
119- - (13. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
120- self .coeffs [1 , 6 ] = 70. * (end_pose [1 ] - start_pose [1 ]) - (36. * eta [0 ] + 15. / 2 * eta [2 ] + 2. / 3 * eta [4 ]) * sa \
121- - (15. / 2 * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
122- - (34. * eta [1 ] - 13. / 2 * eta [3 ] + 1. / 2 * eta [5 ]) * sb \
123- + (13. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ]** 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
130+ self .coeffs [0 , 6 ] = 70. * (end_pose [0 ] - start_pose [0 ]) - (36. * eta [0 ] + 15. / 2 * eta [2 ] + 2. / 3 * eta [4 ]) * ca \
131+ + (15. / 2 * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
132+ - (34. * eta [1 ] - 13. / 2 * eta [3 ] + 1. / 2 * eta [5 ]) * cb \
133+ - (13. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ] **
134+ 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
135+ self .coeffs [1 , 6 ] = 70. * (end_pose [1 ] - start_pose [1 ]) - (36. * eta [0 ] + 15. / 2 * eta [2 ] + 2. / 3 * eta [4 ]) * sa \
136+ - (15. / 2 * eta [0 ]** 2 * kappa [0 ] + 2. / 3 * eta [0 ]** 3 * kappa [1 ] + 2. * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
137+ - (34. * eta [1 ] - 13. / 2 * eta [3 ] + 1. / 2 * eta [5 ]) * sb \
138+ + (13. / 2 * eta [1 ]** 2 * kappa [2 ] - 1. / 2 * eta [1 ] **
139+ 3 * kappa [3 ] - 3. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
124140 # septic (u^7)
125- self .coeffs [0 , 7 ] = - 20. * (end_pose [0 ] - start_pose [0 ]) + (10. * eta [0 ] + 2. * eta [2 ] + 1. / 6 * eta [4 ]) * ca \
126- - (2. * eta [0 ]** 2 * kappa [0 ] + 1. / 6 * eta [0 ]** 3 * kappa [1 ] + 1. / 2 * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
127- + (10. * eta [1 ] - 2. * eta [3 ] + 1. / 6 * eta [5 ]) * cb \
128- + (2. * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
129- self .coeffs [1 , 7 ] = - 20. * (end_pose [1 ] - start_pose [1 ]) + (10. * eta [0 ] + 2. * eta [2 ] + 1. / 6 * eta [4 ]) * sa \
130- + (2. * eta [0 ]** 2 * kappa [0 ] + 1. / 6 * eta [0 ]** 3 * kappa [1 ] + 1. / 2 * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
131- + (10. * eta [1 ] - 2. * eta [3 ] + 1. / 6 * eta [5 ]) * sb \
132- - (2. * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 * kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
141+ self .coeffs [0 , 7 ] = - 20. * (end_pose [0 ] - start_pose [0 ]) + (10. * eta [0 ] + 2. * eta [2 ] + 1. / 6 * eta [4 ]) * ca \
142+ - (2. * eta [0 ]** 2 * kappa [0 ] + 1. / 6 * eta [0 ]** 3 * kappa [1 ] + 1. / 2 * eta [0 ] * eta [2 ] * kappa [0 ]) * sa \
143+ + (10. * eta [1 ] - 2. * eta [3 ] + 1. / 6 * eta [5 ]) * cb \
144+ + (2. * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 *
145+ kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * sb
146+ self .coeffs [1 , 7 ] = - 20. * (end_pose [1 ] - start_pose [1 ]) + (10. * eta [0 ] + 2. * eta [2 ] + 1. / 6 * eta [4 ]) * sa \
147+ + (2. * eta [0 ]** 2 * kappa [0 ] + 1. / 6 * eta [0 ]** 3 * kappa [1 ] + 1. / 2 * eta [0 ] * eta [2 ] * kappa [0 ]) * ca \
148+ + (10. * eta [1 ] - 2. * eta [3 ] + 1. / 6 * eta [5 ]) * sb \
149+ - (2. * eta [1 ]** 2 * kappa [2 ] - 1. / 6 * eta [1 ]** 3 *
150+ kappa [3 ] - 1. / 2 * eta [1 ] * eta [3 ] * kappa [2 ]) * cb
133151 """
134152 eta3_path_segment::calc_point
135-
153+
136154 input
137155 u - parametric representation of a point along the segment, 0 <= u <= 1
138156 returns
139157 (x,y) of point along the segment
140158 """
159+
141160 def calc_point (self , u ):
142161 assert (u >= 0 and u <= 1 )
143162 return self .coeffs .dot (np .array ([1 , u , u ** 2 , u ** 3 , u ** 4 , u ** 5 , u ** 6 , u ** 7 ]))
@@ -148,50 +167,55 @@ def main():
148167 recreate path from reference (see Table 1)
149168 """
150169 path_segments = []
151-
170+
152171 # segment 1: lane-change curve
153172 start_pose = [0 , 0 , 0 ]
154- end_pose = [4 , 1.5 , 0 ]
173+ end_pose = [4 , 1.5 , 0 ]
155174 # NOTE: The ordering on kappa is [kappa_A, kappad_A, kappa_B, kappad_B], with kappad_* being the curvature derivative
156- kappa = [0 , 0 , 0 , 0 ]
157- eta = [4.27 , 4.27 , 0 , 0 , 0 , 0 ]
158- path_segments .append (eta3_path_segment (start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
159-
175+ kappa = [0 , 0 , 0 , 0 ]
176+ eta = [4.27 , 4.27 , 0 , 0 , 0 , 0 ]
177+ path_segments .append (eta3_path_segment (
178+ start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
179+
160180 # segment 2: line segment
161181 start_pose = [4 , 1.5 , 0 ]
162- end_pose = [5.5 , 1.5 , 0 ]
163- kappa = [0 , 0 , 0 , 0 ]
164- eta = [0 , 0 , 0 , 0 , 0 , 0 ]
165- path_segments .append (eta3_path_segment (start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
182+ end_pose = [5.5 , 1.5 , 0 ]
183+ kappa = [0 , 0 , 0 , 0 ]
184+ eta = [0 , 0 , 0 , 0 , 0 , 0 ]
185+ path_segments .append (eta3_path_segment (
186+ start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
166187
167188 # segment 3: cubic spiral
168189 start_pose = [5.5 , 1.5 , 0 ]
169- end_pose = [7.4377 , 1.8235 , 0.6667 ]
170- kappa = [0 , 0 , 1 , 1 ]
171- eta = [1.88 , 1.88 , 0 , 0 , 0 , 0 ]
172- path_segments .append (eta3_path_segment (start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
190+ end_pose = [7.4377 , 1.8235 , 0.6667 ]
191+ kappa = [0 , 0 , 1 , 1 ]
192+ eta = [1.88 , 1.88 , 0 , 0 , 0 , 0 ]
193+ path_segments .append (eta3_path_segment (
194+ start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
173195
174196 # segment 4: generic twirl arc
175197 start_pose = [7.4377 , 1.8235 , 0.6667 ]
176- end_pose = [7.8 , 4.3 , 1.8 ]
177- kappa = [1 , 1 , 0.5 , 0 ]
178- eta = [7 , 10 , 10 , - 10 , 4 , 4 ]
179- path_segments .append (eta3_path_segment (start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
198+ end_pose = [7.8 , 4.3 , 1.8 ]
199+ kappa = [1 , 1 , 0.5 , 0 ]
200+ eta = [7 , 10 , 10 , - 10 , 4 , 4 ]
201+ path_segments .append (eta3_path_segment (
202+ start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
180203
181204 # segment 5: circular arc
182205 start_pose = [7.8 , 4.3 , 1.8 ]
183- end_pose = [5.4581 , 5.8064 , 3.3416 ]
184- kappa = [0.5 , 0 , 0.5 , 0 ]
185- eta = [2.98 , 2.98 , 0 , 0 , 0 , 0 ]
186- path_segments .append (eta3_path_segment (start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
206+ end_pose = [5.4581 , 5.8064 , 3.3416 ]
207+ kappa = [0.5 , 0 , 0.5 , 0 ]
208+ eta = [2.98 , 2.98 , 0 , 0 , 0 , 0 ]
209+ path_segments .append (eta3_path_segment (
210+ start_pose = start_pose , end_pose = end_pose , eta = eta , kappa = kappa ))
187211
188212 # construct the whole path
189213 path = eta3_path (path_segments )
190214
191215 # interpolate at several points along the path
192216 ui = np .linspace (0 , len (path_segments ), 1001 )
193217 pos = np .empty ((2 , ui .size ))
194- for i ,u in enumerate (ui ):
218+ for i , u in enumerate (ui ):
195219 pos [:, i ] = path .calc_path_point (u )
196220
197221 # plot the path
@@ -202,5 +226,6 @@ def main():
202226 plt .title ('Path' )
203227 plt .show ()
204228
229+
205230if __name__ == '__main__' :
206231 main ()
0 commit comments