---
# System prepended metadata

title: Nonimpulsive Orbital Maneuvers

---

1. runge-kutta integrator with vop and without?
2. fuel mass

![image](https://hackmd.io/_uploads/rJ-Zwikx1e.png)
![image](https://hackmd.io/_uploads/rJa9vskxye.png)
![image](https://hackmd.io/_uploads/H1QsDokgyg.png)
![image](https://hackmd.io/_uploads/SkOjDo1g1g.png)
![image](https://hackmd.io/_uploads/Bky2wikx1g.png)
![image](https://hackmd.io/_uploads/S1Q3wjkgJe.png)
![image](https://hackmd.io/_uploads/rkEpvoJgJl.png)
![image](https://hackmd.io/_uploads/SksTDoygJx.png)

FS-9
6889.4908134881943624 km
190.2497292231479378 km
-16.5468474743937080 km
0.0453559761031717 km/sec
-0.9866437758147498 km/sec
7.5404616924289787 km/sec
![image](https://hackmd.io/_uploads/Sk15n6dl1l.png)
x_cross = 2237487;   % unit: mm2
    y_cross = 2141441;   % unit: mm2
    z_cross = 4801999;   % unit: mm2
    sa_max_cross = 3055854;   % unit: mm2
    sa_y_cross = 22965.7;   % unit: mm2
    dm.area    = [x_cross; x_cross; y_cross+sa_y_cross; ...         % a1~a3  unit: mm2
                  y_cross+sa_y_cross; z_cross; z_cross; ...         % a4~a6  unit: mm2
                  sa_max_cross;sa_max_cross;sa_max_cross;sa_max_cross];           
    % normal vector of each area 
    dm.norV     = [ 1  0  0;                                            % n1
                   -1  0  0;                                            % n2
                    0  1  0;                                            % n3
                    0 -1  0;                                            % n4
                    0  0  1;                                            % n5
                    0  0 -1;                                            % n6
                    1  0  0;                                            % n7
                   -1  0  0;                                            % n8
                    0  0  1;                                            % n9
                    0  0 -1];                                           % n10
```matlab=
clc;
clear;
close all;
format long
warning('off', 'all')

% Constants
G = 6.67430e-20; % Gravitational constant in km^3/(kg * s^2)
m1 = 5.97219e24; % Mass of the Earth in kg
RE = 6378.12; % Earth's radius in km
mu = 398600.44189; % Earth's gravitational parameter in km^3/s^2
Cd = 2.2; % Drag coefficient
A = 2.120773439350248; % Cross-sectional area of the satellite in square meters

% Initial conditions (circular orbit)
r0 = [0 7000.000000000003 0]; % Initial position vector in km
v0 = [-7.546053287267834 0 0]; % Initial velocity vector in km/s
Y0 = [r0 v0]; % Initial state vector
    

% Time settings
t0 = 0; % Initial time in seconds
tf = 86400*0.2; % Final time in seconds (2 day)
step_size = 1; % Time step in seconds
thrust_duration = 5828.51662847387; % Thrust duration in seconds

% Propagate the orbit using a custom RK4 solver with J2 and drag
[t, Y] = ode4(@(t, Y) relative_motion_drag_J2(t, Y, thrust_duration), t0, step_size, tf, Y0);

% Extract position and velocity vectors
rvec = Y(:, 1:3);
vvec = Y(:, 4:6);

% Calculate altitude
rmag = vecnorm(rvec, 2, 2);
altitude = rmag - RE;

% Calculate specific orbital energy and angular momentum
specific_energy = zeros(length(t), 1);
specific_angular_momentum = zeros(length(t), 1);
for i = 1:length(t)
    r_i = rvec(i, :);
    v_i = vvec(i, :);
    
    % Calculate the magnitude of the position and velocity vectors
    r_mag = norm(r_i);
    v_mag = norm(v_i);
    
    % Specific orbital energy
    specific_energy(i) = (v_mag^2 / 2) - (mu / r_mag);
    
    % Specific angular momentum magnitude
    h_vec = cross(r_i, v_i);
    specific_angular_momentum(i) = norm(h_vec);
    % Specific orbital energy and semi-major axis
    xi = (norm(v_i)^2 / 2) - (mu / norm(r_i));
    semi_major_axis(i) = -mu / (2 * xi);
    % Calculate semi-minor axis
    %b = semi_major_axis(i) * sqrt(1 - eccentricity(i)^2);
    % Orbital period calculation
    period(i) = 2 * pi * sqrt(semi_major_axis(i)^3 / mu);
end

% Plot specific orbital energy over time
figure;
plot(t / 86400, specific_energy);
xlabel('Time (days)');
ylabel('Specific Orbital Energy (km^2/s^2)');
title('Specific Orbital Energy over Time');
grid on;

% Plot specific angular momentum over time
figure;
plot(t / 86400, specific_angular_momentum);
xlabel('Time (days)');
ylabel('Specific Angular Momentum (km^2/s)');
title('Specific Angular Momentum over Time');
grid on;


% Plot altitude over time
figure;
plot(t / 86400, altitude);
xlabel('Time (days)');
ylabel('Altitude (km)');
title('Altitude over Time');
grid on;

% Create 3D orbit plot
figure;
[xx, yy, zz] = sphere(200);
surf(RE * xx, RE * yy, RE * zz);
colormap(light_blue);
clim([-RE / 100 RE / 100]);
shading interp;

hold on;
plot3(rvec(:, 1), rvec(:, 2), rvec(:, 3), 'k');
plot3(rvec(1, 1), rvec(1, 2), rvec(1, 3), 'go'); % Starting point
plot3(rvec(end, 1), rvec(end, 2), rvec(end, 3), 'ro'); % Ending point
grid on;
axis equal;
xlabel('X (km)');
ylabel('Y (km)');
zlabel('Z (km)');
title('3D Orbit with Thrust Directions');
hold off;

% Theoretical verification
% 理論上的速度增量計算
thrust = 0.032; % 推力 (N)
satellite_mass = 500; % 衛星質量 (kg)

% 推力加速度
thrust_acceleration = thrust / satellite_mass * 1e-3; % km/s^2

% 理論上的速度增量
delta_v_theoretical = thrust_acceleration * thrust_duration; % km/s
fprintf('理論上的速度增量: %.6f km/s\n', delta_v_theoretical);

% 理論上的新速度
v_initial = norm(v0); % 初始速度大小 (km/s)
v_new = v_initial + delta_v_theoretical; % 理論上的新速度大小

% 理論上的新的比機械能
r_initial = norm(r0); % 初始軌道半徑 (km)
epsilon_theoretical = (v_new^2 / 2) - (mu / r_initial);

% 理論上的新的半長軸
a_theoretical = -mu / (2 * epsilon_theoretical); % 新的半長軸 (km)
fprintf('理論上的新的半長軸: %.6f km\n', a_theoretical);

% 計算模擬的最終半長軸
r_final = norm(rvec(end, :)); % 最終軌道半徑 (km)
specific_energy_simulation_final = specific_energy(end);
a_simulation_final = -mu / (2 * specific_energy_simulation_final); % 模擬的最終半長軸 (km)
fprintf('模擬的新的半長軸: %.6f km\n', a_simulation_final);

% 比較半長軸變化
fprintf('理論與模擬半長軸的誤差: %.6f m\n', abs(a_theoretical - a_simulation_final)*1000);
% Helper function for color map
function map = light_blue
    r = 0.8;
    g = r;
    b = 1.0;
    map = [r g b; 0 0 0; r g b];
end

% ODE function that includes drag, J2 perturbation effects, and thrust
function Ydot = relative_motion_drag_J2(t, Y, thrust_duration)
    % Constants
    %J2 = 0.001082626724393;
    J2 = 0;
    mu = 398600.44189; % km^3/s^2
    RE = 6378.12; % Earth's radius in km
    
    % State vector decomposition
    rvector = Y(1:3);
    vvector = Y(4:6);
    
    % Distance from Earth's center
    r = norm(rvector);
    
    % J2 perturbation calculation
    Z = rvector(3);
    Z2 = Z^2;
    r2 = r^2;
    
    ax_J2 = (-mu * rvector(1) / r^3) * (1 - (3/2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 1));
    ay_J2 = (-mu * rvector(2) / r^3) * (1 - (3/2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 1));
    az_J2 = (-mu * rvector(3) / r^3) * (1 - (3/2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 3));
    a_J2 = [ax_J2; ay_J2; az_J2];
    
    % Thrust parameters
    thrust = 0.032; % Thrust in Newtons
    satellite_mass = 500; % Mass of the satellite in kg
    thrust_acceleration = thrust / satellite_mass * 1e-3; % km/s^2
    
    % Apply thrust only within thrust duration
    if t <= thrust_duration
        % Apply thrust along velocity direction
        v = norm(vvector); % Magnitude of velocity
        if v > 0
            v_hat = vvector / v; % Unit vector in velocity direction
        else
            v_hat = [0; 0; 0];
        end
        a_thrust = thrust_acceleration * v_hat; % Thrust acceleration vector
    else
        a_thrust = [0; 0; 0]; % No thrust after thrust duration
    end
    
    % Total acceleration (gravitational + J2 + thrust)
    a_total = a_J2 + a_thrust;
    
    % Return rate of change of position and velocity
    Ydot = [vvector; a_total];
end






```


```matlab=
clc;
clear;
close all;
format long
warning('off','all')

% Constants
G = 6.67430e-20; % Gravitational constant in km^3/(kg * s^2)
m1 = 5.97219e24; % Mass of the Earth in kg
RE = 6378.12; % Earth's radius in km
mu = 398600.44189; % Earth's gravitational parameter in km^3/s^2
Cd = 2.2; % Drag coefficient
A = 2.120773439350248; % Cross-sectional area of the satellite in square meters

% Initial conditions
%[r_ijk,v_ijk] = keplerian2ijk(6915.843310968788,0.05,15,0,0,45);
r0 = [0 7000.000000000003 0]; % Initial position vector in km
v0 = [-7.546053287267834 0 0]; % Initial velocity vector in km/s
Y0 = [r0 v0]; % Initial state vector



% Time settings
t0 = 0; % Initial time in seconds
tf = 86400*7; % Final time in seconds (2 days)

% Global indices for burn1_done and burn2_done
global burn1_done_index burn2_done_index a_trans;
burn1_done_index = [];
burn2_done_index = [];

% Propagate the orbit using 4th order Runge-Kutta method
[t, Y] = ode4(@relative_motion_drag_J2, t0, 1, tf, Y0);

% Extract position and velocity vectors
rvec = Y(:, 1:3);
vvec = Y(:, 4:6);

% Calculate altitude
rmag = vecnorm(rvec, 2, 2);
altitude = rmag - RE;

% Calculate eccentricity at the final state
r_final = rvec(end, :)';
v_final = vvec(end, :)';
r_mag_final = norm(r_final);
v_mag_final = norm(v_final);
e_vec = (cross(v_final, cross(r_final, v_final)) / mu) - (r_final / norm(r_final));
eccentricity = norm(e_vec);

fprintf('Final Orbit Eccentricity: %.12f\n', eccentricity);


% Calculate specific orbital energy
xi = (v_mag_final^2 / 2) - (mu / r_mag_final);

% Calculate the semimajor axis using the relation a = -mu / (2 * xi)
a_final = -mu / (2 * xi);

fprintf('Final Orbit Semimajor Axis: %.12f km\n', a_final);
fprintf('模擬轉移軌道半長軸與理論差距: %.12f km\n', abs(a_final-a_trans));

% Plot altitude over time
figure;
plot(t / 86400, altitude);
xlabel('Time (days)');
ylabel('Altitude (km)');
title('Altitude over Time');
hold on;

% Mark burn start points on the altitude plot
if ~isempty(burn1_done_index)
    plot(burn1_done_index / 86400, altitude(find(t == int64(burn1_done_index))), 'bo', 'MarkerFaceColor', 'b', 'DisplayName', 'Burn 1 Start');
end

legend;

% Print indices for burn1_done and burn2_done
disp('Times for burn1_done:');
disp(burn1_done_index);
index1 = find(t == int64(burn1_done_index));



% Create a 3D plot of the orbit
figure;
[xx, yy, zz] = sphere(200);
surf(RE * xx, RE * yy, RE * zz)
colormap(light_blue)
clim([-RE / 100 RE / 100])
shading interp

% Draw and label the X, Y, and Z axes
line([0 2 * RE], [0 0], [0 0]);
text(2 * RE + RE / 10, 0, 0, 'x')
line([0 0], [0 2 * RE], [0 0]);
text(0, 2 * RE + RE / 10, 0, 'y')
line([0 0], [0 0], [0 2 * RE]);
text(0, 0, 2 * RE + RE / 10, 'z')

hold on
plot3(rvec(1:index1, 1), rvec(1:index1, 2), rvec(1:index1, 3), 'b')
plot3(rvec(index1:end, 1), rvec(index1:end, 2), rvec(index1:end, 3), 'r')
plot3(rvec(1, 1), rvec(1, 2), rvec(1, 3), 'go'); % Starting point
plot3(rvec(index1, 1), rvec(index1, 2), rvec(index1, 3), 'b+'); % Burn 1 start point

plot3(rvec(end, 1), rvec(end, 2), rvec(end, 3), 'ro'); % Ending point



% Set graph properties
grid on
axis equal
xlabel('km')
ylabel('km')
zlabel('km')
title('3D Orbit');
legend;

% Custom colormap function
function map = light_blue
    r = 0.8;
    g = r;
    b = 1.0;
    map = [r g b; 0 0 0; r g b];
end

% Function to compute the derivatives of the state vector
function Ydot = relative_motion_drag_J2(t, Y)
    % Declare global variables
    global burn1_done_index burn2_done_index a_trans;

    % Earth's J2 coefficient and gravitational parameter
    %J2 = 0.001082626724393;
    J2 = 0;
    mu = 398600.44189; % km^3/s^2
    RE = 6378.12; % Earth's radius in km
    
    % Extract position and velocity vectors
    rvector = Y(1:3);
    vvector = Y(4:6);
    
    % J2 perturbation calculation
    r = norm(rvector);  
    Z = rvector(3);
    Z2 = Z^2;
    r2 = r^2;
    ax_J2 = (-mu * rvector(1) / r^3) * (1 - (3 / 2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 1));
    ay_J2 = (-mu * rvector(2) / r^3) * (1 - (3 / 2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 1));
    az_J2 = (-mu * rvector(3) / r^3) * (1 - (3 / 2) * J2 * (RE^2 / r2) * (5 * Z2 / r2 - 3));
    a_J2 = [ax_J2; ay_J2; az_J2];
    
    % Thrust calculation
    a_thrust = [0; 0; 0];
    thrust =0.032; % Thrust in Newtons
    satellite_mass = 475; % Mass of the satellite in kg
    thrust_acceleration = thrust / satellite_mass * 1e-3; % in km/s^2
    persistent burnStartTime burn_time1 burn_time2 burn1_done burn2_done; % Persistent variable to record burn start time
    if t >=5723.671751785554   
        if isempty(burnStartTime) 
            burn1_done = false;
            burn2_done = false;
            target_altitude = 700; % Target orbit altitude in km
            r1 = norm(rvector); % Initial orbit radius in km
            fprintf("R1:%.3f Km\n",r1-RE);
            r2 = RE + target_altitude; % Final orbit radius in km
            fprintf("R2:%.3f Km\n",r2-RE);
            % Calculate the velocities for the Hohmann transfer
            a_trans = (r1 + r2) / 2;
            fprintf("a_trans:%.12f Km\n",a_trans);
            v1 = sqrt(mu / r1);
            v1 = norm(vvector); % Initial orbit velocity
            fprintf("V1:%f Km/s\n",v1);
            v2 = sqrt(mu / r2); % Final orbit velocity
            fprintf("V2:%f Km/s\n",v2);
            va = sqrt((2 * mu / r1) - (mu / a_trans)); % Transfer orbit apogee velocity
            fprintf("Va:%f Km/s\n",va);
            vb = sqrt((2 * mu / r2) - (mu / a_trans)); % Transfer orbit perigee velocity
            fprintf("Vb:%f Km/s\n",vb);
            % Delta-v for the transfer
            delta_v1 = va - v1; % First burn
            fprintf("delta_v1:%f m/s\n",delta_v1*1000);
            % Thrust parameters
            %thrust =15000; % Thrust in Newtons
            Isp = 1244; % Specific impulse in seconds
            g0 = 9.81e-3; % Standard gravity in km/s^2
            satellite_mass = 475; % Mass of the satellite in kg
            mdot = thrust/(g0*Isp); % mass flow rate kg/s
            v_e = Isp * g0; % exhaust speed km/s
         
            % Calculate burn times for the Hohmann transfer
            burn_time1 = delta_v1 / thrust_acceleration; % Time for first burn in seconds
            fprintf("burn_time1:%f s\n",burn_time1);
            burnStartTime = t; % Record the start time of the burn
        end

        % Calculate true anomaly for periapsis (burn 1) and apoapsis (burn 2)    
        if ~burn1_done
            % Calculate true anomaly for periapsis
            e_vec = cross(vvector, cross(rvector, vvector)) / mu - rvector / norm(rvector);
            e = norm(e_vec);
            true_anomaly = acos(dot(e_vec, rvector) / (e * norm(rvector)));
            if dot(rvector, vvector) < 0
                true_anomaly = 2 * pi - true_anomaly;
            end
            % Start burn 1 at periapsis
            if abs(true_anomaly) <= 1.745329251994330e-04
                burnStartTime = t; % Start time for burn 1
                burn1_done = true;
                burn1_done_index = [burn1_done_index; t]; % Store time
                fprintf("True Anomaly (Burn 1): %.12f\n", rad2deg(true_anomaly));
                fprintf("burnStartTime: %.5f\n", burnStartTime);
                fprintf("burn1_done: %d\n", burn1_done);
            end
       
        end
        
        if burn1_done && (t >= burnStartTime && t <= burnStartTime + burn_time1)
            vvector_normalized = vvector / norm(vvector);
            a_thrust = (thrust_acceleration * vvector_normalized);
        end
    
        
    end
    % Total acceleration
    a_total = a_J2 + a_thrust;
    
    % Output derivative of state vector
    Ydot = [vvector; a_total];
end
```