@@ -122,16 +122,20 @@ def test_kinematic_car(self, vehicle_flat, poly):
122
122
vehicle_flat , T , ud , x0 , return_x = True )
123
123
np .testing .assert_allclose (x , xd , atol = 0.01 , rtol = 0.01 )
124
124
125
- def test_kinematic_car_cost_constr (self , vehicle_flat ):
125
+ def test_flat_cost_constr (self ):
126
+ # Double integrator system
127
+ sys = ct .ss ([[0 , 1 ], [0 , 0 ]], [[0 ], [1 ]], [[1 , 0 ]], 0 )
128
+ flat_sys = fs .LinearFlatSystem (sys )
129
+
126
130
# Define the endpoints of the trajectory
127
- x0 = [0. , - 2. , 0. ]; u0 = [10. , 0. ]
128
- xf = [100. , 2. , 0. ]; uf = [10. , 0. ]
131
+ x0 = [1 , 0 ]; u0 = [0 ]
132
+ xf = [0 , 0 ]; uf = [0 ]
129
133
Tf = 10
130
134
T = np .linspace (0 , Tf , 500 )
131
135
132
136
# Find trajectory between initial and final conditions
133
137
traj = fs .point_to_point (
134
- vehicle_flat , Tf , x0 , u0 , xf , uf , basis = fs .PolyFamily (6 ))
138
+ flat_sys , Tf , x0 , u0 , xf , uf , basis = fs .PolyFamily (8 ))
135
139
x , u = traj .eval (T )
136
140
137
141
np .testing .assert_array_almost_equal (x0 , x [:, 0 ])
@@ -142,11 +146,13 @@ def test_kinematic_car_cost_constr(self, vehicle_flat):
142
146
# Solve with a cost function
143
147
timepts = np .linspace (0 , Tf , 10 )
144
148
cost_fcn = opt .quadratic_cost (
145
- vehicle_flat , np .diag ([0 , 0.1 , 0 ]), np . diag ([ 0.1 , 1 ]) , x0 = xf , u0 = uf )
149
+ flat_sys , np .diag ([0 , 0 ]), 1 , x0 = xf , u0 = uf )
146
150
147
151
traj_cost = fs .point_to_point (
148
- vehicle_flat , timepts , x0 , u0 , xf , uf , cost = cost_fcn ,
149
- basis = fs .PolyFamily (8 )
152
+ flat_sys , timepts , x0 , u0 , xf , uf , cost = cost_fcn ,
153
+ basis = fs .PolyFamily (8 ),
154
+ # initial_guess='lstsq',
155
+ # minimize_kwargs={'method': 'trust-constr'}
150
156
)
151
157
152
158
# Verify that the trajectory computation is correct
@@ -159,22 +165,18 @@ def test_kinematic_car_cost_constr(self, vehicle_flat):
159
165
# Make sure that we got a different answer than before
160
166
assert np .any (np .abs (x - x_cost ) > 0.1 )
161
167
162
- # Make sure that the previous computation had large y deviation
163
- assert np .any (x_cost [1 , :] > 2.6 )
164
-
165
168
# Re-solve with constraint on the y deviation
166
- # timepts = np.array([0, 0.5*Tf, 0.8*Tf, Tf])
167
- constraints = (
168
- sp .optimize .LinearConstraint ,
169
- np .array ([[0 , 1 , 0 , 0 , 0 ]]), - 2.6 , 2.6 )
169
+ lb , ub = [- 2 , - 0.1 ], [2 , 0 ]
170
+ lb , ub = [- 2 , np .min (x_cost [1 ])* 0.95 ], [2 , 1 ]
171
+ constraints = [opt .state_range_constraint (flat_sys , lb , ub )]
172
+
173
+ # Make sure that the previous solution violated at least one constraint
174
+ assert np .any (x_cost [0 , :] < lb [0 ]) or np .any (x_cost [0 , :] > ub [0 ]) \
175
+ or np .any (x_cost [1 , :] < lb [1 ]) or np .any (x_cost [1 , :] > ub [1 ])
176
+
170
177
traj_const = fs .point_to_point (
171
- vehicle_flat , timepts , x0 , u0 , xf , uf , cost = cost_fcn ,
178
+ flat_sys , timepts , x0 , u0 , xf , uf , cost = cost_fcn ,
172
179
constraints = constraints , basis = fs .PolyFamily (8 ),
173
- # minimize_kwargs={
174
- # 'method': 'trust-constr',
175
- # 'options': {'finite_diff_rel_step': 0.01},
176
- # # 'hess': lambda x: np.zeros((x.size, x.size))
177
- # }
178
180
)
179
181
180
182
# Verify that the trajectory computation is correct
@@ -184,8 +186,10 @@ def test_kinematic_car_cost_constr(self, vehicle_flat):
184
186
np .testing .assert_array_almost_equal (xf , x_const [:, - 1 ])
185
187
np .testing .assert_array_almost_equal (uf , u_const [:, - 1 ])
186
188
187
- # Make sure that the solution respects the bounds
188
- assert np .any (x_const [:, 1 ] < 2.6 )
189
+ # Make sure that the solution respects the bounds (with some slop)
190
+ for i in range (x_const .shape [0 ]):
191
+ assert np .all (x_const [i ] >= lb [i ] * 1.02 )
192
+ assert np .all (x_const [i ] <= ub [i ] * 1.02 )
189
193
190
194
def test_bezier_basis (self ):
191
195
bezier = fs .BezierFamily (4 )
@@ -223,3 +227,43 @@ def test_bezier_basis(self):
223
227
# Exception check
224
228
with pytest .raises (ValueError , match = "index too high" ):
225
229
bezier .eval_deriv (4 , 0 , time )
230
+
231
+ def test_point_to_point_errors (self ):
232
+ """Test error and warning conditions in point_to_point()"""
233
+ # Double integrator system
234
+ sys = ct .ss ([[0 , 1 ], [0 , 0 ]], [[0 ], [1 ]], [[1 , 0 ]], 0 )
235
+ flat_sys = fs .LinearFlatSystem (sys )
236
+
237
+ # Define the endpoints of the trajectory
238
+ x0 = [1 , 0 ]; u0 = [0 ]
239
+ xf = [0 , 0 ]; uf = [0 ]
240
+ Tf = 10
241
+ T = np .linspace (0 , Tf , 500 )
242
+
243
+ # Cost function
244
+ timepts = np .linspace (0 , Tf , 10 )
245
+ cost_fcn = opt .quadratic_cost (
246
+ flat_sys , np .diag ([1 , 1 ]), 1 , x0 = xf , u0 = uf )
247
+
248
+ # Try to optimize with insufficient degrees of freedom
249
+ with pytest .warns (UserWarning , match = "optimization not possible" ):
250
+ traj = fs .point_to_point (
251
+ flat_sys , timepts , x0 , u0 , xf , uf , cost = cost_fcn ,
252
+ basis = fs .PolyFamily (6 ))
253
+
254
+ # Make sure we still solved the problem
255
+ x , u = traj .eval (timepts )
256
+ np .testing .assert_array_almost_equal (x0 , x [:, 0 ])
257
+ np .testing .assert_array_almost_equal (u0 , u [:, 0 ])
258
+ np .testing .assert_array_almost_equal (xf , x [:, - 1 ])
259
+ np .testing .assert_array_almost_equal (uf , u [:, - 1 ])
260
+
261
+ # Solve with the errors in the various input arguments
262
+ with pytest .raises (ValueError , match = "Initial state: Wrong shape" ):
263
+ traj = fs .point_to_point (flat_sys , timepts , np .zeros (3 ), u0 , xf , uf )
264
+ with pytest .raises (ValueError , match = "Initial input: Wrong shape" ):
265
+ traj = fs .point_to_point (flat_sys , timepts , x0 , np .zeros (3 ), xf , uf )
266
+ with pytest .raises (ValueError , match = "Final state: Wrong shape" ):
267
+ traj = fs .point_to_point (flat_sys , timepts , x0 , u0 , np .zeros (3 ), uf )
268
+ with pytest .raises (ValueError , match = "Final input: Wrong shape" ):
269
+ traj = fs .point_to_point (flat_sys , timepts , x0 , u0 , xf , np .zeros (3 ))
0 commit comments