@@ -50,44 +50,48 @@ class OptimalControlProblem():
50
50
integral_cost : callable
51
51
Function that returns the integral cost given the current state
52
52
and input. Called as integral_cost(x, u).
53
- trajectory_constraints : list of tuples , optional
53
+ trajectory_constraints : list of constraints , optional
54
54
List of constraints that should hold at each point in the time
55
- vector. Each element of the list should consist of a tuple with
56
- first element given by :meth:`~scipy.optimize.LinearConstraint` or
57
- :meth:`~scipy.optimize.NonlinearConstraint` and the remaining
58
- elements of the tuple are the arguments that would be passed to
59
- those functions. The constraints will be applied at each time
60
- point along the trajectory.
55
+ vector. Each element of the list should be an object of type
56
+ :class:`~scipy.optimize.LinearConstraint` with arguments `(A, lb,
57
+ ub)` or :class:`~scipy.optimize.NonlinearConstraint` with arguments
58
+ `(fun, lb, ub)`. The constraints will be applied at each time point
59
+ along the trajectory.
61
60
terminal_cost : callable, optional
62
61
Function that returns the terminal cost given the current state
63
62
and input. Called as terminal_cost(x, u).
64
- initial_guess : 1D or 2D array_like
65
- Initial inputs to use as a guess for the optimal input. The
66
- inputs should either be a 2D vector of shape (ninputs, horizon)
67
- or a 1D input of shape (ninputs,) that will be broadcast by
68
- extension of the time axis.
69
63
trajectory_method : string, optional
70
64
Method to use for carrying out the optimization. Currently supported
71
65
methods are 'shooting' and 'collocation' (continuous time only). The
72
66
default value is 'shooting' for discrete time systems and
73
67
'collocation' for continuous time systems
68
+ initial_guess : (tuple of) 1D or 2D array_like
69
+ Initial states and/or inputs to use as a guess for the optimal
70
+ trajectory. For shooting methods, an array of inputs for each time
71
+ point should be specified. For collocation methods, the initial
72
+ guess is either the input vector or a tuple consisting guesses for
73
+ the state and the input. Guess should either be a 2D vector of
74
+ shape (ninputs, ntimepts) or a 1D input of shape (ninputs,) that
75
+ will be broadcast by extension of the time axis.
74
76
log : bool, optional
75
77
If `True`, turn on logging messages (using Python logging module).
76
- Use ``logging.basicConfig`` to enable logging output (e.g., to a file).
77
- kwargs : dict, optional
78
- Additional parameters (passed to :func:`scipy.optimal.minimize`).
78
+ Use :py:func:`logging.basicConfig` to enable logging output
79
+ (e.g., to a file).
79
80
80
81
Returns
81
82
-------
82
83
ocp : OptimalControlProblem
83
84
Optimal control problem object, to be used in computing optimal
84
85
controllers.
85
86
86
- Additional parameters
87
- ---------------------
87
+ Other Parameters
88
+ ----------------
88
89
basis : BasisFamily, optional
89
90
Use the given set of basis functions for the inputs instead of
90
91
setting the value of the input at each point in the timepts vector.
92
+ terminal_constraints : list of constraints, optional
93
+ List of constraints that should hold at the terminal point in time,
94
+ in the same form as `trajectory_constraints`.
91
95
solve_ivp_method : str, optional
92
96
Set the method used by :func:`scipy.integrate.solve_ivp`.
93
97
solve_ivp_kwargs : str, optional
@@ -174,20 +178,6 @@ def __init__(
174
178
if kwargs :
175
179
raise TypeError ("unrecognized keyword(s): " , str (kwargs ))
176
180
177
- # Process trajectory constraints
178
- def _process_constraints (constraint_list , name ):
179
- if isinstance (constraint_list , tuple ):
180
- constraint_list = [constraint_list ]
181
- elif not isinstance (constraint_list , list ):
182
- raise TypeError (f"{ name } constraints must be a list" )
183
-
184
- # Make sure that we recognize all of the constraint types
185
- for ctype , fun , lb , ub in constraint_list :
186
- if not ctype in [opt .LinearConstraint , opt .NonlinearConstraint ]:
187
- raise TypeError (f"unknown { name } constraint type { ctype } " )
188
-
189
- return constraint_list
190
-
191
181
self .trajectory_constraints = _process_constraints (
192
182
trajectory_constraints , "trajectory" )
193
183
self .terminal_constraints = _process_constraints (
@@ -1005,9 +995,6 @@ def solve_ocp(
1005
995
If True, assume that 2D input arrays are transposed from the standard
1006
996
format. Used to convert MATLAB-style inputs to our format.
1007
997
1008
- kwargs : dict, optional
1009
- Additional parameters (passed to :func:`scipy.optimal.minimize`).
1010
-
1011
998
Returns
1012
999
-------
1013
1000
res : OptimalControlResult
@@ -1443,3 +1430,45 @@ def _evaluate_output_range_constraint(x, u):
1443
1430
1444
1431
# Return a nonlinear constraint object based on the polynomial
1445
1432
return (opt .NonlinearConstraint , _evaluate_output_range_constraint , lb , ub )
1433
+
1434
+ #
1435
+ # Utility functions
1436
+ #
1437
+
1438
+ #
1439
+ # Process trajectory constraints
1440
+ #
1441
+ # Constraints were originally specified as a tuple with the type of
1442
+ # constraint followed by the arguments. However, they are now specified
1443
+ # directly as SciPy constraint objects.
1444
+ #
1445
+ # The _process_constraints() function will covert everything to a consistent
1446
+ # internal representation (currently a tuple with the constraint type as the
1447
+ # first element.
1448
+ #
1449
+ def _process_constraints (clist , name ):
1450
+ if isinstance (
1451
+ clist , (tuple , opt .LinearConstraint , opt .NonlinearConstraint )):
1452
+ clist = [clist ]
1453
+ elif not isinstance (clist , list ):
1454
+ raise TypeError (f"{ name } constraints must be a list" )
1455
+
1456
+ # Process individual list elements
1457
+ constraint_list = []
1458
+ for constraint in clist :
1459
+ if isinstance (constraint , tuple ):
1460
+ # Original style of constraint
1461
+ ctype , fun , lb , ub = constraint
1462
+ if not ctype in [opt .LinearConstraint , opt .NonlinearConstraint ]:
1463
+ raise TypeError (f"unknown { name } constraint type { ctype } " )
1464
+ constraint_list .append (constraint )
1465
+ elif isinstance (constraint , opt .LinearConstraint ):
1466
+ constraint_list .append (
1467
+ (opt .LinearConstraint , constraint .A ,
1468
+ constraint .lb , constraint .ub ))
1469
+ elif isinstance (constraint , opt .NonlinearConstraint ):
1470
+ constraint_list .append (
1471
+ (opt .NonlinearConstraint , constraint .fun ,
1472
+ constraint .lb , constraint .ub ))
1473
+
1474
+ return constraint_list
0 commit comments