最速度降线问题
Problem Description
The brachistochrone optimal control problem is stated as follows. Minimize the cost functional
\begin{align}
J = t_f \tag{1.1}
\end{align}
subject to the dynamic constraints:
\begin{align}
\dot{x} &= v(t) \cos u(t) \tag{2.1} \\
\dot{y} &= v(t) \sin u(t) \tag{2.2} \\
\dot{v} &= g \cos u(t) \tag{2.3}
\end{align}
and the boundary conditions:
\begin{align}
x(0) = 0, \ & x(t_f) = 2 \tag{3.1} \\
y(0) = 0, \ & y(t_f) = 2 \tag{3.2} \\
v(0) = 0, \ & v(t_f) = \text{Free} \tag{3.3}
\end{align}
Note
Brachistochrone, a classic optimal control problem is to compute the brachistochrone curve of fastest descent. A point mass must slide without friction and with constant gravitational force to an fixed end point in the shortest time. The planar curve on which a body subjected only to the force of gravity will slide (without friction) between two points in the least possible time.
Modeling
NN = 100
prob = multi_stage_problem('brachistochrone', NN + 1)
g = 9.81
t0 = 0
x0, y0, v0 = 0, 0, 0
xMin, xMax = 0, 50
yMin, yMax = 0, 50
vMin, vMax = 0, 50
uMin, uMax = 0, 50
tfMin, tfMax =0.01, 1000.0
xf, yf = prob.parameters(['xf', 'yf'], stage_dependent=False)
x = prob.variable('x', hard_lowerbound=xMin, hard_upperbound=xMax)
y = prob.variable('y', hard_lowerbound=yMin, hard_upperbound=yMax)
v = prob.variable('v', hard_lowerbound=vMin, hard_upperbound=vMax)
u = prob.variable('u', hard_lowerbound=uMin, hard_upperbound=uMax)
tf = prob.variable('tf', hard_lowerbound=tfMin, hard_upperbound=tfMax)
""" ode """
dxdt = [v * sin(u), v * cos(u), g * cos(u), 0]
ts = tf / NN
ode = differential_equation(
state=[x, y, v, tf],
state_dot=dxdt,
stepsize=ts,
discretization_method='trapezoid')
prob.equality(ode)
# minimize fuel consumption
obj = general_objective(tf)
prob.end_objective(obj)
seq = general_equality([x - x0, y - y0, v - v0])
prob.start_equality(seq)
eeq = general_equality([x - xf, y - yf])
prob.end_equality(eeq)
option = codegen_option()
codegen = code_generator()
codegen.codegen(prob, option)
Solving
#include "brachistochrone_solver.h"
#include "brachistochrone_prob.h"
#include <stdio.h>
#include <string.h>
int main {
/* params */
Brachistochrone_Problem prob;
Brachistochrone_Option option;
Brachistochrone_WorkSpace ws;
Brachistochrone_Output output;
brachistochrone_init(&prob, &option, &ws);
prob.param[BRACHISTOCHRONE_PARAM_XF] = 2.0;
prob.param[BRACHISTOCHRONE_PARAM_YF] = 2.0;
/* option */
option.max_num_iter = 50;
option.print_level = 2;
for (i = 0; i < BRACHISTOCHRONE_DIM_N; i++) {
/* initial guess */
const double ratio = (double)(BRACHISTOCHRONE_DIM_N - 1 - i) / (double)(BRACHISTOCHRONE_DIM_N - 1);
// const double ratio = 1.0;
ws.primal.var[i][BRACHISTOCHRONE_VAR_X] = (1.0 - ratio) * prob.param[BRACHISTOCHRONE_PARAM_XF];
ws.primal.var[i][BRACHISTOCHRONE_VAR_Y] = (1.0 - ratio) * prob.param[BRACHISTOCHRONE_PARAM_YF];
ws.primal.var[i][BRACHISTOCHRONE_VAR_V] = 0.0;
ws.primal.var[i][BRACHISTOCHRONE_VAR_U] = 0.0;
ws.primal.var[i][BRACHISTOCHRONE_VAR_TF] = 1.0;
}
brachistochrone_solve(&prob, &option, &ws, &output);
return 0;
}
Solution
the solution to the brachistochrone optimal control problem using OPTIMake is shown in the figures below.