Skip to content

最速度降线问题

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.