Use Case: Custom propagated orbit
This example was generated on 2024-11-18T22:29:37.076.
Once the general structure of the FrameSystem
is understood, we can pass to a use case in which we want to build and exploit our frame system to perform computations inserting a custom orbit. This becomes especially crucial in complex cases like Trajectory Optimization and Navigation Analysis.
In such scenarios, the trajectory is under design, and the trajectory information might not be completely available. Moreover, in these cases derivatives could be required for various quantities such as time, states, and parameters.
In this context, we shall remember that FrameTransformations
is able to perform operations, including AD, on the frames independent variable, e.g. only time.
A proper orbit representation is essential to avoid perturbation confusion and ensure proper custom orbit handling.
Frame system setup
First of all, a new FrameSystem
shall be created.
using FrameTransformations
G = FrameSystem{4,Float64}()
add_axes!(G, :ICRF, 1)
add_point!(G, :Earth, 399, 1)
As the orbit considered in this example is custom, there is no requirement to load ephemeris.
Custom orbit model
A custom orbit model is then required. In this case a simple two-body problem is considered but more complex models can be used. We interface with SciML
ODE solvers to compute the trajectory solution.
using OrdinaryDiffEq
using DiffEqBase
Now we create the problem with a given initial condition, time-span and gravitational parameter.
function two_body!(du, u, p, t)
μ = p[1]
r = sqrt(u[1]^2 + u[2]^2 + u[3]^2)
r3 = r^3
du[1] = u[4]
du[2] = u[5]
du[3] = u[6]
du[4] = -μ * u[1] / r3
du[5] = -μ * u[2] / r3
du[5] = -μ * u[2] / r3
nothing
end
u0 = [7000.0, 0.0, 0.0, 0.0, 8.0, 0.1]
p = [398600.0,]
tspan = (0, 10 * 86400.0)
prob = ODEProblem(two_body!, u0, tspan, p)
ODEProblem with uType Vector{Float64} and tType Float64. In-place: true
timespan: (0.0, 864000.0)
u0: 6-element Vector{Float64}:
7000.0
0.0
0.0
0.0
8.0
0.1
It is possible to create a new node using directly the solution of the ODE problem or before the problem is solved, using the integrator:
integrator = DiffEqBase.__init(prob, Vern9(), abstol=1e-14, reltol=1e-12)
add_point_dynamical!(G, :SC, -1, 399, 1, t -> @views(integrator.sol(t)[1:3]), t -> integrator.sol(t))
Now we can compute the trajectory:
solve!(integrator)
retcode: Success
Interpolation: specialized 9th order lazy interpolation
t: 767-element Vector{Float64}:
0.0
0.002100410678471327
0.0047599230055715425
0.008955696574592512
0.014405191722968853
0.02256127192121507
0.03376908947224431
0.049589055530138385
0.0698982062387515
0.09881641196938389
⋮
806236.5951903301
813554.5837279536
821095.7757502404
828936.367091165
837208.97355692
845655.5468850702
853693.9091403671
862493.6137650727
864000.0
u: 767-element Vector{Vector{Float64}}:
[7000.0, 0.0, 0.0, 0.0, 8.0, 0.1]
[6999.999999982056, 0.01680328542775626, 0.0002100410678471327, -1.7086197886483454e-5, 7.999999999979493, 0.1]
[6999.999999907846, 0.03807938404440524, 0.0004759923005571542, -3.8720516530803896e-5, 7.9999999998946825, 0.1]
[6999.99999967378, 0.07164557259562712, 0.000895569657459251, -7.285185009298929e-5, 7.999999999627178, 0.1]
[6999.999999155986, 0.11524153377911914, 0.0014405191722968852, -0.00011718182490732019, 7.999999999035414, 0.1]
[6999.999997929675, 0.1804901753519266, 0.002256127192121507, -0.00018352904054244176, 7.999999997633916, 0.1]
[6999.999995361795, 0.2701527157182867, 0.003376908947224431, -0.000274701205297076, 7.999999994699195, 0.1]
[6999.999989998091, 0.3967124440521604, 0.004958905553013839, -0.0004033917861508917, 7.999999988569248, 0.1]
[6999.999980127922, 0.5591856493808606, 0.00698982062387515, -0.0005686005096037746, 7.999999977289055, 0.1]
[6999.999960283645, 0.7905312942599749, 0.00988164119693839, -0.0008038412593625989, 7.999999954609882, 0.1]
⋮
[27780.683963325602, 42359.01446895586, 80623.65951903291, -0.8025971884101836, 0.7920170040605534, 0.1]
[21593.404005364973, 47617.06581630905, 81355.45837279527, -0.8843405807263419, 0.643265710217164, 0.1]
[14685.747014284721, 51862.035932975115, 82109.57757502396, -0.9434414826071104, 0.48150113994807625, 0.1]
[7133.1289576091995, 54962.451067493384, 82893.63670911641, -0.9787751475642218, 0.30899747628535834, 0.1]
[-1024.0952950747117, 56763.854488823155, 83720.89735569191, -0.9888316844294007, 0.12684156398017055, 0.1]
[-9325.026533480774, 57062.54147480205, 84565.55468850693, -0.9723707350002112, -0.055126342355960874, 0.1]
[-17000.28781860142, 55946.09286142069, 85369.39091403662, -0.9337249254505049, -0.22127499568585487, 0.1]
[-24945.126440130833, 53237.49061776463, 86249.36137650716, -0.8681287897346082, -0.3921808825049796, 0.1]
[-26242.78437442029, 52625.65098316583, 86399.9999999999, -0.8546412436047252, -0.4200754020972222, 0.1]
From now on we can use the frame system with the :SC
custom node:
vector6(G, :Earth, :SC, :ICRF, 123456.0)
6-element StaticArraysCore.SVector{6, Float64} with indices SOneTo(6):
-12000.809592690548
10523.77670590901
12345.600000000011
-2.7588011391226344
-2.247097800159169
0.1
This page was generated using Literate.jl.