## 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.

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.

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