@@ -71,12 +71,12 @@ The dynamics is
7171 \begin{align}
7272 F(x, u; a) =
7373 \begin{bmatrix}
74- ax_1 + 0.2x_1^2 - 1.2 x_2 + u \\
75- \sin(x_2) + 0.2 x_1^3 - u
74+ 0.98 \sin(x_1) + x_2 \\
75+ 0.1x_1^2 - 0.5 x_1 + a x_2 + u
7676 \end{bmatrix},
7777 \end{align}
7878\] </div >
79- where $a$ is a constant parameter. Suppose the stage cost
79+ where $a$ is a parameter. Suppose the stage cost
8080function is
8181<div class =" math " >
8282\[
@@ -91,69 +91,117 @@ cost function is
9191<div class =" math " >
9292\[
9393 \begin{align}
94- V_f(x; x^{\mathrm{ref}}) = 10 \| x_N-x^{\mathrm{ref}}\| ^2.
94+ V_f(x; x^{\mathrm{ref}}) = 100 \| x_N-x^{\mathrm{ref}}\| ^2.
9595 \end{align}
9696\] </div >
97- Lastly, we
98- This can be done as follows:
97+ Lastly, we have the state constraint $x_t \geq x_ {\rm min}$, where $x_ {\rm min}$ is a parameter,
98+ and the hard input constraints $|u_t| \leq 0.2$.
99+
100+ <br >
101+
102+ This optimal control problem can be constructed as follows:
99103
100104``` python
101- # Check this out...
102- ocp = og.ocp.OptimalControlProblem(nx = 2 , nu = 1 , horizon = 5 ,
103- shooting = og.ocp.ShootingMethod.SINGLE )
105+ optimizer_name = " ocp_alm"
106+
107+ # Construct the OCP
108+ ocp = og.ocp.OptimalControlProblem(nx = 2 , nu = 1 , horizon = 20 )
109+
110+ # Define the parameters
104111ocp.add_parameter(" x0" , 2 )
105112ocp.add_parameter(" xref" , 2 , default = [0.0 , 0.0 ])
113+ ocp.add_parameter(" q" , 1 , default = 1 )
114+ ocp.add_parameter(" r" , 1 , default = 0.1 )
115+ ocp.add_parameter(" a" , 1 , default = 1 )
116+ ocp.add_parameter(" xmin" , 1 , default = - 1 )
106117
107118# System dynamics
108- ocp.with_dynamics(lambda x , u , param :
109- cs.vertcat(x[ 0 ] + u [0 ], x[1 ] - u[ 0 ]))
110-
111- # A typical stage cost function
119+ ocp.with_dynamics(lambda x , u , param :
120+ cs.vertcat(0.98 * cs.sin(x [0 ]) + x[1 ],
121+ 0.1 * x[ 0 ] ** 2 - 0.5 * x[ 0 ] + param[ " a " ] * x[ 1 ] + u[ 0 ]))
122+ # Stage cost
112123ocp.with_stage_cost(
113124 lambda x , u , param , _t :
114- cs.dot(x - param[" xref" ], x - param[" xref" ]) + 0.01 * cs.dot(u, u)
125+ param[" q" ] * cs.dot(x - param[" xref" ], x - param[" xref" ])
126+ + param[" r" ] * cs.dot(u, u)
115127)
116128
117- # Terminal cost function
129+ # Terminal cost
118130ocp.with_terminal_cost(
119- lambda x , param :
120- 2.0 * cs.dot(x - param[" xref" ], x - param[" xref" ])
131+ lambda x , param : 100 * cs.dot(x - param[" xref" ], x - param[" xref" ])
121132)
122133
123- # Input constraints
124- ocp.with_input_constraints(og.constraints.Rectangle([- 0.4 ], [0.4 ]))
125-
126- # State/input joint constraints
134+ # State constraint: x1 <= xmax, imposed with ALM
127135ocp.with_path_constraint(
128- lambda x , u , param , _t : cs.fmax(0.0 , x[0 ] - 1.5 )
136+ lambda x , u , param , _t : x[1 ] - param[" xmin" ],
137+ kind = " alm" ,
138+ set_c = og.constraints.Rectangle([0 .], [1000.0 ]),
129139)
140+
141+ # Input constraints
142+ ocp.with_input_constraints(og.constraints.BallInf(radius = 0.2 ))
130143```
131144
132145Having defined the above OCP, we can build the optimizer...
133146
147+ <!-- DOCUSAURUS_CODE_TABS-->
134148
149+ <!-- Direct intercafe-->
135150``` python
136- solver_config = ...
137- optimizer = og.ocp.OCPBuilder(
138- ocp,
139- metadata = og.config.OptimizerMeta().with_optimizer_name(" ocp_single_tcp" ),
140- build_configuration = og.config.BuildConfiguration()
141- .with_build_directory(" ." )
142- .with_tcp_interface_config(
143- tcp_interface_config = og.config.TcpServerConfiguration(bind_port = 3391 )
144- ),
145- solver_configuration = solver_config,
146- ).build()
151+ ocp_optimizer = og.ocp.OCPBuilder(
152+ ocp,
153+ metadata = og.config.OptimizerMeta().with_optimizer_name(optimizer_name),
154+ build_configuration = og.config.BuildConfiguration()
155+ .with_build_python_bindings().with_rebuild(True ),
156+ solver_configuration = og.config.SolverConfiguration()
157+ .with_tolerance(1e-5 )
158+ .with_delta_tolerance(1e-5 )
159+ .with_preconditioning(True )
160+ .with_penalty_weight_update_factor(1.8 )
161+ .with_max_inner_iterations(2000 )
162+ .with_max_outer_iterations(40 ),
163+ ).build()
147164```
148165
166+ <!-- TCP socket interface-->
167+ ``` python
168+ ocp_optimizer = og.ocp.OCPBuilder(
169+ ocp,
170+ metadata = og.config.OptimizerMeta().with_optimizer_name(optimizer_name),
171+ build_configuration = og.config.BuildConfiguration()
172+ .with_tcp_interface_config(
173+ tcp_interface_config = og.config.TcpServerConfiguration(bind_port = 3391 )
174+ ).with_rebuild(True ),
175+ solver_configuration = og.config.SolverConfiguration()
176+ .with_tolerance(1e-5 )
177+ .with_delta_tolerance(1e-5 )
178+ .with_preconditioning(True )
179+ .with_penalty_weight_update_factor(1.8 )
180+ .with_max_inner_iterations(2000 )
181+ .with_max_outer_iterations(40 ),
182+ ).build()
183+ ```
184+
185+ <!-- END_DOCUSAURUS_CODE_TABS-->
186+
149187The optimizer can then be called as follows:
150188
151189``` python
152- result = single_optimizer .solve(x0 = [1 , - 1 ], xref = [ 0 , 0 ] )
190+ result = ocp_optimizer .solve(x0 = [0.4 , 0.2 ], q = 30 , r = 1 , a = 0.8 , xmin = - 0.2 )
153191```
154192
155- and note that the parameter ` xref=xref ` is optional; if not specified,
156- the default value will be used (the default was set when we constructed the
157- OCP).
193+ and note that all parameters except ` x0 ` are optional; if not specified,
194+ their default values will be used (the defaults were set when we constructed the
195+ OCP). We can now plot the optimal sequence of inputs (` result.inputs ` )
196+
197+ <img src =" /optimization-engine/img/ocp-inputs.png " alt =" Seq. inputs " width =" 60% " >
198+
199+ and the corresponding sequence of states (` result.states ` )
200+
201+ <img src =" /optimization-engine/img/ocp-states.png " alt =" Seq. states " width =" 60% " >
202+
203+ The object ` result ` contains the above sequences of inputs and states and additional
204+ information about the solution, solver time, Lagrange multipliers, etc.
205+
158206
159207## Step-by-step documentation
0 commit comments