Hohmann transfers are a well-known maneuver used to change the semi-major axis of an orbit. The Spacecraft Control Toolbox allows you to compute the required velocity changes, and integrate them into a full simulation.

In this demonstration, we create a 6U CubeSat that has 3 orthogonal reaction wheels and a single hydrazine thruster. The thruster is aligned with the body x-axis and must be aligned with the velocity vector to do the maneuver. An ideal Hohmann maneuver is done with impulsive burns at two points in the orbit. In reality, with a thruster, we have to do a finite burn.

The Hohmann transfer is computed with the following Spacecraft Control Toolbox code:

```
rI = [-7000;0;0];
vI = [0;-sqrt(mu/Mag(rI));0];
OrbMnvrHohmann(Mag(rI),rF);
[dV,tOF] = OrbMnvrHohmann(Mag(rI),rF);
```

The first time `OrbMnvrHohmann`

is called, it generates the plot below of the planned Hohmann transfer. The function computes the delta-V and also the time of flight, which will be used to determine the start time of the second thruster burn.

We create a short script with numerical integration to implement the maneuver using a thruster. The burn durations are computed based on the thrust and the mass of the spacecraft. In this case, they are about three minutes long. The maneuver is quite small, so the mass change is not important. The attitude control system uses the `PID3Axis`

function which is a general-purpose attitude control algorithm. The simulation is a for loop, shown below. The ECI vector for the burn is passed to the attitude control system, which updates every step of the simulation.

```
% Simulation loop
for k = 1:n
% Update the controller
dC.eci_vector = uBurn(:,kMnvr);
[tRWA, dC] = PID3Axis( x(7:10), dC );
% Start the first burn
inMnvr = false;
if( t(k) > tStart(1) && t(k) < tEnd(1) )
inMnvr = true;
end
% Switch orientation
if( t(k) > tEnd(1) )
kMnvr = 2;
end
% Start the second burn
if( t(k) > tStart(2) && t(k) < tEnd(2) )
inMnvr = true;
end
if( inMnvr )
dRHS.force = thrustE*QTForm(x(7:10),dC.body_vector)*nToKN; % kN
else
dRHS.force = [0;0;0];
end
el = RV2El(x(1:3),x(4:6));
xP(:,k) = [x;tRWA;Mag(dRHS.force)/nToKN;el(1);el(5)];
% Right hand side
dRHS.torqueRWA = -tRWA;
x = RK4(@RHSRWAOrbit,x,dT,0,dRHS);
end
```

The maneuver logic just waits a quarter orbit then performs the first burn, by applying the thrust along the body vector. It then waits for the time of flight and then starts the next burn. The start and stop times are pre-computed. RK4 is Fourth Order Runge-Kutta, a popular numerical algorithm included with the toolbox.

At the final orbit radius an attitude maneuver is needed to reorient for the final burn.

The spacecraft body rates, in the body frame, during the maneuver are shown below.

The reaction wheel rates are shown below. The simulation does not model any particular wheel. Friction is not included in the simulation, although the right-hand-side function can include friction.

The wheel torques and rocket thrust are shown below. The thruster is a 0.2 lbf hydrazine thruster that is based on the Aerojet-Rocketdyne MR-103. The PID controller does not demand much torque.

The semi-major axis and eccentricity are shown below. The middle portion is during the transfer orbit.

The eccentricity is zero at the start and finish. Note the slope in both eccentricity and semi-major axis due to the finite acceleration. At the end of the simulation, we print the achieved orbital elements:

```
Final SMA 7099.72 km
SMA error 0.28 km
Final e 1.3e-05
```

The result is very close to the ideal solution!

This post shows how you can easily integrate attitude and orbit control. Email us for more information! We’d be happy to share the script. We can also offer a 30 day demo to let you explore the software.