Example: Orbit Raising

Difficulty: Intermediate

The problem was originally presented by [1].

Consider the orbit transfer problem illustrated below

The objective is find the optimal control profile such that radius of the final orbit is maximized:

With scaling and nondimensionalization (e.g. using Astronomical unit), system dynamics can be expressed as

with

Additionally, we have path constraint,

simple bounds on variables,

and boundary conditions


We require the numerical solution to fulfill the following accuracy criteria

Formulate the problem in ICLOCS2

In internal model defination file OrbitRaising_Dynamics_Internal.m

We can specify the system dynamics in function OrbitRaising_Dynamics_Internal with

r=x(:,1);theta=x(:,2);v_r=x(:,3);v_theta=x(:,4);
u_1=u(:,1);u_2=u(:,2);

T1=vdat.T1;
md=vdat.md;
dx=[v_r,v_theta./r,(v_theta.*v_theta)./r-r.^(-2)+(T1./(1-md*t)).*u_1,...
    (-v_r.*v_theta)./r+(T1./(1-md*t)).*u_2];

g_eq=u_1.*u_1+u_2.*u_2-1;

For this example problem, we have one equality path constraints, so function OrbitRaising_Dynamics_Internal need to return the value of variable dx and g_eq .

Similarly, the (optional) simulation dynamics can be specifed in function OrbitRaising_Dynamics_Sim.m .


In problem defination file OrbitRaising.m

First we provide the function handles for system dynamics with

InternalDynamics=@OrbitRaising_Dynamics_Internal;
SimDynamics=@OrbitRaising_Dynamics_Sim;

The optional files providing analytic derivatives can be left empty as we use finite difference this time

problem.analyticDeriv.gradCost=[];
problem.analyticDeriv.hessianLagrangian=[];
problem.analyticDeriv.jacConst=[];

and finally the function handle for the settings file is given as.

problem.settings=@settings_OrbitRaising;

Then we may define the time variables with

problem.time.t0_min=0;
problem.time.t0_max=0;
guess.t0=0;

and

problem.time.tf_min=3.32;     
problem.time.tf_max=3.32; 
guess.tf=3.32;

For state variables, we need to provide the initial conditions

problem.states.x0=[1 0 0 1]; 

bounds on intial conditions

problem.states.x0l=[1 0 0 1]; 
problem.states.x0u=[1 0 0 1];  

state bounds

problem.states.xl=[0 0 0 0];
problem.states.xu=[2 pi 2 2]; 

bounds on the absolute local and global (integrated) discretization error of state variables

problem.states.xErrorTol_local=[0.01 deg2rad(0.01) 0.01 0.01];
problem.states.xErrorTol_integral=[0.01 deg2rad(0.01) 0.01 0.01]; 

tolerance for state variable box constraint violation

problem.states.xConstraintTol=[0.01 deg2rad(0.01) 0.01 0.01]; 

terminal state bounds

problem.states.xfl=[0 0 0 0]; 
problem.states.xfu=[2 pi 2 2]; 

and an initial guess of the state trajectory (optional but recommended)

guess.states(:,1)=[1 1.4];
guess.states(:,2)=[0 2.5];
guess.states(:,3)=[0 0.05];
guess.states(:,4)=[1 0.8]; 

Lastly for control variables, we need to define simple bounds

problem.inputs.ul=[-1 -1];
problem.inputs.uu=[1 1];

bounds on the first control action

problem.inputs.u0l=[-1 -1];
problem.inputs.u0u=[1 1]; 

tolerance for control variable box constraint violation

problem.inputs.uConstraintTol=[0.01 0.01]; 

as well as an initial guess of the input trajectory (optional but recommended)

guess.inputs(:,1)=[0.4 -0.7];
guess.inputs(:,2)=[.9 0.7];

We need to specify the bounds for the constraint functions . We have one equality path constraint

problem.constraints.ng_eq=1;
problem.constraints.gTol_eq=[0.01];

but do not have any inequality path constraint

problem.constraints.gl=[];
problem.constraints.gu=[];
problem.constraints.gTol_neq=[];

Additionally, we have two boundary constraint functions

problem.constraints.bl=[0 0];
problem.constraints.bu=[0 0];
problem.constraints.bTol=[1e-02 1e-02];

We may store the necessary problem parameters used in the functions

problem.data.T1=0.1405;
problem.data.md=0.0749;

Since this problem only has a Mayer (boundary) cost , and no Lagrange (stage) cost ,we simply have

boundaryCost=-xf(1);
stageCost = 0*t;

for sub-function E_unscaled and L_unscaled respectively.


For this example problem, we do have two boundary constraints (in addition to varialbe simple bounds). Thus we need to specify sub-routines b_unscaled as

bc=[xf(4)-sqrt(1/xf(1));xf(3)];

Main script main_OrbitRaising.m

Now we can fetch the problem and options, solve the resultant NLP, and generate some plots for the solution.

[problem,guess]=WindshearGoAround;          % Fetch the problem definition
% options= problem.settings(5,8);                  % for hp method
options= problem.settings(20);                  % for h method
[solution,MRHistory]=solveMyProblem( problem,guess,options);
[ tv, xv, uv ] = simulateSolution( problem, solution, 'ode113', 0.01 );

Note the last line of code will generate an open-loop simulation, applying the obtained input trajectory to the dynamics defined in WindshearGoAround_Dynamics_Sim.m , using the Matlab builtin ode113 ODE solver with a step size of 0.01.

Results from ICLOCS2

Using the Hermite-Simpson discretization scheme of ICLOCS2, the following state and input trajectories are obtained under a mesh refinement scheme starting with 40 mesh points. The computation time with IPOPT (NLP convergence tol set to 1e-09) is about 12 seconds for 2 mesh refinement iterations together, using finite difference derivative calculations on an Intel i7-6700 desktop computer. Subsequent recomputation using the same mesh and warm starting will take on average 0.5 seconds and about 20 iterations.

Figure 1: Optimal state trajectory for the orbit raising problem (dash black line indicate the open-loop simulation of the obtained solution)
Figure 2: Optimal input trajectory for the orbit raising problem (dash black line indicate the open-loop simulation of the obtained solution)

Converting the nondimensionalized time variable back yield

which is equivalent to a journey time of approximately 193 days.

Alternative Formulation

Optimal control problems that are mathematically equivalent may yield different results in compuatational efficiency. Here we demonstrate the benefit of using an alternative formulation of the same orbit raising problem. Instead of using the two elements of the direction vector as control input, we can reformulate the problem that directly uses the directional angle as control inputs. In this way, we can reduce the number of states and inputs by 1 each, and also eliminate the need of one equality path constraint. In addition, faster computations can be obtainable using analytic derivatives infomation rather than finite difference computations.

As the result, using the same Hermite-Simpson discretization with the same 40 mesh points at start, the following state and input trajectories are obtained after refining the mesh 2 time as well. The computation time with IPOPT (NLP convergence tol set to 1e-09) is now reduced to just 1.4 seconds . Subsequent recomputation using the same mesh and warm starting will take on average 0.3 seconds and less than 20 iterations.

Figure 3: Optimal state trajectory for the orbit raising problem with alternative formulation(dash black line indicate the open-loop simulation of the obtained solution)
Figure 4: Optimal input trajectory for the orbit raising problem with alternative formulation(dash black line indicate the open-loop simulation of the obtained solution)

[1] A.E. Bryson, and Y.C. Ho, Applied Optimal Control, Hemisphere Publishing, New York, 1975.