Skip to content

Commit 6e8195a

Browse files
committed
address doc-related TODOs; rename optimal_{ocp,oep}
1 parent e82670e commit 6e8195a

18 files changed

Lines changed: 108 additions & 144 deletions

control/flatsys/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
using the `BasisFamily` class. The resulting trajectory is return
1717
as a `SystemTrajectory` object and can be evaluated using the
1818
`SystemTrajectory.eval` member function. Alternatively, the
19-
`solve_flat_ocp` function can be used to solve an optimal control
19+
`solve_flat_optimal` function can be used to solve an optimal control
2020
problem with trajectory and final costs or constraints.
2121
2222
The docstring examples assume that the following import commands::
@@ -29,9 +29,9 @@
2929

3030
# Basis function families
3131
from .basis import BasisFamily as BasisFamily
32-
from .poly import PolyFamily as PolyFamily
3332
from .bezier import BezierFamily as BezierFamily
3433
from .bspline import BSplineFamily as BSplineFamily
34+
from .poly import PolyFamily as PolyFamily
3535

3636
# Classes
3737
from .systraj import SystemTrajectory as SystemTrajectory
@@ -41,4 +41,5 @@
4141

4242
# Package functions
4343
from .flatsys import point_to_point as point_to_point
44+
from .flatsys import solve_flat_optimal as solve_flat_optimal
4445
from .flatsys import solve_flat_ocp as solve_flat_ocp

control/flatsys/flatsys.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ def traj_const(null_coeffs):
656656

657657

658658
# Solve a point to point trajectory generation problem for a flat system
659-
def solve_flat_ocp(
659+
def solve_flat_optimal(
660660
sys, timepts, x0=0, u0=0, trajectory_cost=None, basis=None,
661661
terminal_cost=None, trajectory_constraints=None,
662662
initial_guess=None, params=None, **kwargs):
@@ -996,3 +996,7 @@ def traj_const(null_coeffs):
996996

997997
# Return a function that computes inputs and states as a function of time
998998
return systraj
999+
1000+
1001+
# Convenience aliases
1002+
solve_flat_ocp = solve_flat_optimal

control/flatsys/systraj.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class SystemTrajectory:
1818
1919
The `SystemTrajectory` class is used to represent the trajectory
2020
of a (differentially flat) system. Used by the `point_to_point`
21-
and `solve_flat_ocp` functions to return a trajectory.
21+
and `solve_flat_optimal` functions to return a trajectory.
2222
2323
Parameters
2424
----------

control/lti.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def __init__(self, inputs=1, outputs=1, states=None, name=None, **kwargs):
3838
super().__init__(
3939
name=name, inputs=inputs, outputs=outputs, states=states, **kwargs)
4040

41-
# TODO: update ss, tf docstrings to use this one as the primary
4241
def __call__(self, x, squeeze=None, warn_infinite=True):
4342
"""Evaluate system transfer function at point in complex plane.
4443

control/optimal.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
88
This module provides support for optimization-based controllers for
99
nonlinear systems with state and input constraints. An optimal
10-
control problem can be solved using the `solve_ocp` function or set up
11-
using the `OptimalControlProblem` class and then solved using the
12-
`~OptimalControlProblem.compute_trajectory` method. Utility functions
13-
are available to define common cost functions and input/state
14-
constraints. Optimal estimation problems can be solved using the
15-
`solve_oep` function or by using the `OptimalEstimationProblem` class
16-
and the `~OptimalEstimationProblem.compute_estimate` method..
10+
control problem can be solved using the `solve_optimal_trajectory`
11+
function or set up using the `OptimalControlProblem` class and then
12+
solved using the `~OptimalControlProblem.compute_trajectory` method.
13+
Utility functions are available to define common cost functions and
14+
input/state constraints. Optimal estimation problems can be solved
15+
using the `solve_optimal_estimate` function or by using the
16+
`OptimalEstimationProblem` class and the
17+
`~OptimalEstimationProblem.compute_estimate` method..
1718
1819
The docstring examples assume the following import commands::
1920
@@ -760,7 +761,6 @@ def _simulate_states(self, x0, inputs):
760761
#
761762

762763
# Compute the optimal trajectory from the current state
763-
# TODO: update docstring to refer to primary function (?)
764764
def compute_trajectory(
765765
self, x, squeeze=None, transpose=None, return_states=True,
766766
initial_guess=None, print_summary=True, **kwargs):
@@ -1017,7 +1017,7 @@ def __init__(
10171017

10181018

10191019
# Compute the input for a nonlinear, (constrained) optimal control problem
1020-
def solve_ocp(
1020+
def solve_optimal_trajectory(
10211021
sys, timepts, X0, cost, trajectory_constraints=None,
10221022
terminal_cost=None, terminal_constraints=None, initial_guess=None,
10231023
basis=None, squeeze=None, transpose=None, return_states=True,
@@ -1220,7 +1220,7 @@ def create_mpc_iosystem(
12201220
12211221
constraints : list of tuples, optional
12221222
List of constraints that should hold at each point in the time
1223-
vector. See `solve_ocp` for more details.
1223+
vector. See `solve_optimal_trajectory` for more details.
12241224
12251225
terminal_cost : callable, optional
12261226
Function that returns the terminal cost given the final state
@@ -2020,7 +2020,7 @@ def __init__(
20202020

20212021

20222022
# Compute the finite horizon estimate for a nonlinear system
2023-
def solve_oep(
2023+
def solve_optimal_estimate(
20242024
sys, timepts, Y, U, trajectory_cost, X0=None,
20252025
trajectory_constraints=None, initial_guess=None,
20262026
squeeze=None, print_summary=True, **kwargs):
@@ -2047,7 +2047,7 @@ def solve_oep(
20472047
Mean value of the initial condition (defaults to 0).
20482048
trajectory_constraints : list of tuples, optional
20492049
List of constraints that should hold at each point in the time
2050-
vector. See `solve_ocp` for more information.
2050+
vector. See `solve_optimal_trajectory` for more information.
20512051
control_indices : int, slice, or list of int or string, optional
20522052
Specify the indices in the system input vector that correspond to
20532053
the control inputs. For more information on possible values, see
@@ -2544,3 +2544,8 @@ def _process_constraints(clist, name):
25442544
constraint.lb, constraint.ub))
25452545

25462546
return constraint_list
2547+
2548+
2549+
# Convenience aliases
2550+
solve_ocp = solve_optimal_trajectory
2551+
solve_oep = solve_optimal_estimate

control/statesp.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -774,34 +774,7 @@ def __call__(self, x, squeeze=None, warn_infinite=True):
774774
in the complex plane, where `x` is `s` for continuous-time systems
775775
and `z` for discrete-time systems.
776776
777-
By default, a (complex) scalar will be returned for SISO systems
778-
and a p x m array will be return for MIMO systems with m inputs and
779-
p outputs. This can be changed using the `squeeze` keyword.
780-
781-
To evaluate at a frequency `omega` in radians per second,
782-
enter ``x = omega * 1j`` for continuous-time systems,
783-
``x = exp(1j * omega * dt)`` for discrete-time systems, or
784-
use the `~LTI.frequency_response` method.
785-
786-
Parameters
787-
----------
788-
x : complex or complex 1D array_like
789-
Complex value(s) at which transfer function will be evaluated.
790-
squeeze : bool, optional
791-
Squeeze output, as described below. Default value can be set
792-
using `config.defaults['control.squeeze_frequency_response']`.
793-
warn_infinite : bool, optional If set to False, turn off
794-
divide by zero warning.
795-
796-
Returns
797-
-------
798-
fresp : complex ndarray
799-
The value of the system transfer function at `x`. If the system
800-
is SISO and `squeeze` is not True, the shape of the array matches
801-
the shape of `x`. If the system is not SISO or `squeeze` is
802-
False, the first two dimensions of the array are indices for the
803-
output and input and the remaining dimensions match `x`. If
804-
`squeeze` is True then single-dimensional axes are removed.
777+
See `LTI.__call__` for details.
805778
806779
Examples
807780
--------

control/stochsys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ def create_estimator_iosystem(
433433
References
434434
----------
435435
.. [1] R. M. Murray, `Optimization-Based Control
436-
<https://fbswiki.org/OBC`_, 2013.
436+
<https://fbswiki.org/OBC>`_, 2013.
437437
438438
"""
439439

control/tests/docstrings_test.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
keyword_skiplist = {
4949
control.input_output_response: ['method'],
5050
control.nyquist_plot: ['color'], # separate check
51-
control.optimal.solve_ocp: ['method', 'return_x'], # deprecated
51+
control.optimal.solve_optimal_trajectory:
52+
['method', 'return_x'], # deprecated
5253
control.sisotool: ['kvect'], # deprecated
5354
control.nyquist_response: ['return_contour'], # deprecated
5455
control.create_estimator_iosystem: ['state_labels'], # deprecated
@@ -61,7 +62,7 @@
6162
control.flatsys.point_to_point: [
6263
'method', 'options', # minimize_kwargs
6364
],
64-
control.flatsys.solve_flat_ocp: [
65+
control.flatsys.solve_flat_optimal: [
6566
'method', 'options', # minimize_kwargs
6667
],
6768
control.optimal.OptimalControlProblem: [

control/tests/flatsys_test.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def test_kinematic_car_ocp(
198198
with warnings.catch_warnings():
199199
warnings.filterwarnings(
200200
'ignore', message="unable to solve", category=UserWarning)
201-
traj_ocp = fs.solve_flat_ocp(
201+
traj_ocp = fs.solve_flat_optimal(
202202
vehicle_flat, timepts, x0, u0,
203203
trajectory_cost=traj_cost,
204204
trajectory_constraints=input_constraints,
@@ -384,7 +384,7 @@ def test_flat_solve_ocp(self, basis):
384384
terminal_cost = opt.quadratic_cost(
385385
flat_sys, 1e3, 1e3, x0=xf, u0=uf)
386386

387-
traj_cost = fs.solve_flat_ocp(
387+
traj_cost = fs.solve_flat_optimal(
388388
flat_sys, timepts, x0, u0,
389389
terminal_cost=terminal_cost, basis=basis)
390390

@@ -398,7 +398,7 @@ def test_flat_solve_ocp(self, basis):
398398
# Solve with trajectory and terminal cost functions
399399
trajectory_cost = opt.quadratic_cost(flat_sys, 0, 1, x0=xf, u0=uf)
400400

401-
traj_cost = fs.solve_flat_ocp(
401+
traj_cost = fs.solve_flat_optimal(
402402
flat_sys, timepts, x0, u0, terminal_cost=terminal_cost,
403403
trajectory_cost=trajectory_cost, basis=basis)
404404

@@ -421,7 +421,7 @@ def test_flat_solve_ocp(self, basis):
421421
assert np.any(x_cost[0, :] < lb[0]) or np.any(x_cost[0, :] > ub[0]) \
422422
or np.any(x_cost[1, :] < lb[1]) or np.any(x_cost[1, :] > ub[1])
423423

424-
traj_const = fs.solve_flat_ocp(
424+
traj_const = fs.solve_flat_optimal(
425425
flat_sys, timepts, x0, u0,
426426
terminal_cost=terminal_cost, trajectory_cost=trajectory_cost,
427427
trajectory_constraints=constraints, basis=basis,
@@ -444,7 +444,7 @@ def test_flat_solve_ocp(self, basis):
444444
# Use alternative keywords as well
445445
nl_constraints = [
446446
(sp.optimize.NonlinearConstraint, lambda x, u: x, lb, ub)]
447-
traj_nlconst = fs.solve_flat_ocp(
447+
traj_nlconst = fs.solve_flat_optimal(
448448
flat_sys, timepts, x0, u0,
449449
trajectory_cost=trajectory_cost, terminal_cost=terminal_cost,
450450
trajectory_constraints=nl_constraints, basis=basis,
@@ -668,7 +668,7 @@ def test_solve_flat_ocp_errors(self):
668668
# Solving without basis specified should be OK (may generate warning)
669669
with warnings.catch_warnings():
670670
warnings.simplefilter("ignore")
671-
traj = fs.solve_flat_ocp(flat_sys, timepts, x0, u0, cost_fcn)
671+
traj = fs.solve_flat_optimal(flat_sys, timepts, x0, u0, cost_fcn)
672672
x, u = traj.eval(timepts)
673673
np.testing.assert_array_almost_equal(x0, x[:, 0])
674674
if not traj.success:
@@ -681,40 +681,40 @@ def test_solve_flat_ocp_errors(self):
681681

682682
# Solving without a cost function generates an error
683683
with pytest.raises(TypeError, match="cost required"):
684-
traj = fs.solve_flat_ocp(flat_sys, timepts, x0, u0)
684+
traj = fs.solve_flat_optimal(flat_sys, timepts, x0, u0)
685685

686686
# Try to optimize with insufficient degrees of freedom
687687
with pytest.raises(ValueError, match="basis set is too small"):
688-
traj = fs.solve_flat_ocp(
688+
traj = fs.solve_flat_optimal(
689689
flat_sys, timepts, x0, u0, trajectory_cost=cost_fcn,
690690
basis=fs.PolyFamily(2))
691691

692692
# Solve with the errors in the various input arguments
693693
with pytest.raises(ValueError, match="Initial state: Wrong shape"):
694-
traj = fs.solve_flat_ocp(
694+
traj = fs.solve_flat_optimal(
695695
flat_sys, timepts, np.zeros(3), u0, cost_fcn)
696696
with pytest.raises(ValueError, match="Initial input: Wrong shape"):
697-
traj = fs.solve_flat_ocp(
697+
traj = fs.solve_flat_optimal(
698698
flat_sys, timepts, x0, np.zeros(3), cost_fcn)
699699

700700
# Constraint that isn't a constraint
701701
with pytest.raises(TypeError, match="must be a list"):
702-
traj = fs.solve_flat_ocp(
702+
traj = fs.solve_flat_optimal(
703703
flat_sys, timepts, x0, u0, cost_fcn,
704704
trajectory_constraints=np.eye(2), basis=fs.PolyFamily(8))
705705

706706
# Unknown constraint type
707707
with pytest.raises(TypeError, match="unknown constraint type"):
708-
traj = fs.solve_flat_ocp(
708+
traj = fs.solve_flat_optimal(
709709
flat_sys, timepts, x0, u0, cost_fcn,
710710
trajectory_constraints=[(None, 0, 0, 0)],
711711
basis=fs.PolyFamily(8))
712712

713713
# Method arguments, parameters
714-
traj_method = fs.solve_flat_ocp(
714+
traj_method = fs.solve_flat_optimal(
715715
flat_sys, timepts, x0, u0, trajectory_cost=cost_fcn,
716716
basis=fs.PolyFamily(6), minimize_method='slsqp')
717-
traj_kwarg = fs.solve_flat_ocp(
717+
traj_kwarg = fs.solve_flat_optimal(
718718
flat_sys, timepts, x0, u0, trajectory_cost=cost_fcn,
719719
basis=fs.PolyFamily(6), minimize_kwargs={'method': 'slsqp'})
720720
np.testing.assert_allclose(
@@ -723,7 +723,7 @@ def test_solve_flat_ocp_errors(self):
723723

724724
# Unrecognized keywords
725725
with pytest.raises(TypeError, match="unrecognized keyword"):
726-
traj_method = fs.solve_flat_ocp(
726+
traj_method = fs.solve_flat_optimal(
727727
flat_sys, timepts, x0, u0, cost_fcn, solve_ivp_method=None)
728728

729729
@pytest.mark.parametrize(

control/tests/kwargs_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,15 @@ def test_response_plot_kwargs(data_fcn, plot_fcn, mimo):
308308
'zpk': test_unrecognized_kwargs,
309309
'flatsys.point_to_point':
310310
flatsys_test.TestFlatSys.test_point_to_point_errors,
311+
'flatsys.solve_flat_optimal':
312+
flatsys_test.TestFlatSys.test_solve_flat_ocp_errors,
311313
'flatsys.solve_flat_ocp':
312314
flatsys_test.TestFlatSys.test_solve_flat_ocp_errors,
313315
'flatsys.FlatSystem.__init__': test_unrecognized_kwargs,
314316
'optimal.create_mpc_iosystem': optimal_test.test_mpc_iosystem_rename,
317+
'optimal.solve_optimal_trajectory': optimal_test.test_ocp_argument_errors,
315318
'optimal.solve_ocp': optimal_test.test_ocp_argument_errors,
319+
'optimal.solve_optimal_estimate': optimal_test.test_oep_argument_errors,
316320
'optimal.solve_oep': optimal_test.test_oep_argument_errors,
317321
'ControlPlot.set_plot_title': freqplot_test.test_suptitle,
318322
'FrequencyResponseData.__init__':

0 commit comments

Comments
 (0)