From bdb439e3675d031ae6181e7b400ce4c89047886d Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Thu, 15 Oct 2020 18:45:14 -0400 Subject: [PATCH 01/12] Adding colorful orbit printing, perifocal tracking * `Orbit` now tracks positions/velocities in the perifocal frame too * `Base.show` overloaded for `Orbit` types (colorful output!) --- Manifest.toml | 9 +- Project.toml | 3 +- src/Plots/plot_twobody.jl | 8 +- src/Propagators/propagate_twobody.jl | 27 +++-- src/TwoBody/TwoBody.jl | 7 +- src/TwoBody/kepler.jl | 22 ++-- src/TwoBody/twobody_calculations.jl | 175 +++++++++++++++++++-------- src/TwoBody/twobody_states.jl | 102 +++++++++++++--- test/TwoBody/test_twobody.jl | 16 +-- 9 files changed, 263 insertions(+), 106 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 1400dce3..875b4821 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -144,6 +144,11 @@ git-tree-sha1 = "f0464e499ab9973b43c20f8216d088b61fda80c6" uuid = "adafc99b-e345-5852-983c-f28acb93d879" version = "0.2.2" +[[Crayons]] +git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.0.4" + [[DataAPI]] git-tree-sha1 = "176e23402d80e7743fc26c19c681bfb11246af32" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" @@ -276,9 +281,9 @@ version = "0.4.0" [[FFMPEG_jll]] deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] -git-tree-sha1 = "13a934b9e74a8722bf1786c989de346a9602e695" +git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f" uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" -version = "4.3.1+2" +version = "4.3.1+4" [[FastClosures]] git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" diff --git a/Project.toml b/Project.toml index b2a43b42..37b078a4 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.5.0" [deps] ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" +Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" @@ -18,7 +19,6 @@ UnitfulAngles = "6fb2a4bd-7999-5318-a3b2-8ad61056cd98" UnitfulAstro = "6112ee07-acf9-5e0f-b108-d242c714bf9f" [compat] -julia = "1" ComponentArrays = "0.8" DifferentialEquations = "6.15" PhysicalConstants = "0.2" @@ -29,3 +29,4 @@ StaticArrays = "0.12" Unitful = "1.4" UnitfulAngles = "0.6" UnitfulAstro = "1.0" +julia = "1" diff --git a/src/Plots/plot_twobody.jl b/src/Plots/plot_twobody.jl index ce619402..e87e8073 100644 --- a/src/Plots/plot_twobody.jl +++ b/src/Plots/plot_twobody.jl @@ -32,14 +32,12 @@ function plot3d(sols::TwobodyPropagationResult; kwargs...) fig = plot() - plot!(fig, ustrip.(u"km", map(x->x.r̅[1], sols.step)), - ustrip.(u"km", map(x->x.r̅[2], sols.step)), - ustrip.(u"km", map(x->x.r̅[3], sols.step)), + plot!(fig, ustrip.(u"km", map(x->x.rᵢ[1], sols.step)), + ustrip.(u"km", map(x->x.rᵢ[2], sols.step)), + ustrip.(u"km", map(x->x.rᵢ[3], sols.step)), label="Orbit Position") plot!(fig; options...) - display(fig) - return fig end \ No newline at end of file diff --git a/src/Propagators/propagate_twobody.jl b/src/Propagators/propagate_twobody.jl index af5d9623..56044ed5 100644 --- a/src/Propagators/propagate_twobody.jl +++ b/src/Propagators/propagate_twobody.jl @@ -10,10 +10,15 @@ Struct to hold two-body propagation results. """ -struct TwobodyPropagationResult <: PropagationResult - - t::AbstractVector{Unitful.Time{Float64}} - step +struct TwobodyPropagationResult{ + T<:Unitful.Time, + O<:TwoBodySystem, + VT<:AbstractVector{T}, + VO<:AbstractVector{O} +} <: PropagationResult + + t::VT + step::VO ode_solution::ODESolution end @@ -31,8 +36,8 @@ function twobody_tic(du, u, p, t) # in [2] allows the use of mixed units through the ComponentArrays # package. - du.r̅ = u.v̅ - du.v̅ = -p.μ * (u.r̅ ./ norm(u.r̅,2)^3) + du.rᵢ = u.vᵢ + du.vᵢ = -p.μ * (u.rᵢ ./ norm(u.rᵢ,2)^3) end @@ -60,13 +65,13 @@ function propagate(orbit::Orbit, options = merge(defaults, kwargs) # Initial conditions - r₀ = Array(ustrip.(u"m",orbit.r̅)) - v₀ = Array(ustrip.(u"m/s", orbit.v̅)) + r₀ = Array(ustrip.(u"m",orbit.rᵢ)) + v₀ = Array(ustrip.(u"m/s", orbit.vᵢ)) # Define the problem (modified from [2]) problem = ODEProblem( twobody_tic, - ComponentArray((r̅=r₀, v̅=v₀)), + ComponentArray((rᵢ=r₀, vᵢ=v₀)), ustrip.(u"s", (0.0u"s", Δt)), ComponentArray((μ=ustrip(u"m^3 / s^2", orbit.body.μ)))) @@ -75,8 +80,8 @@ function propagate(orbit::Orbit, # Return PropagationResult structure return TwobodyPropagationResult( - u"s" * sols.t, - map(x -> Orbit(u"m" * x.r̅, u"m/s" * x.v̅, orbit.body), sols.u), + u"s" .* sols.t, + map(x -> Orbit(u"m" * x.rᵢ, u"m/s" * x.vᵢ, orbit.body), sols.u), sols ) diff --git a/src/TwoBody/TwoBody.jl b/src/TwoBody/TwoBody.jl index a270e201..034843b9 100644 --- a/src/TwoBody/TwoBody.jl +++ b/src/TwoBody/TwoBody.jl @@ -12,11 +12,12 @@ using ..AbstractTypes using Reexport using Logging -using Base: isapprox, isequal +using Base: isapprox, isequal, show using LinearAlgebra: ×, ⋅, norm using DifferentialEquations using ComponentArrays using StaticArrays +using Crayons # Newton's Gravitation Constant import PhysicalConstants.CODATA2018 @@ -28,12 +29,12 @@ G = 1.0 * CODATA2018.G export TwoBodySystem, Orbit, AbstractConic, Circular, InvalidOrbit, Elliptical, Parabolic, Hyperbolic, Invalid, Body, CelestialBody, Sun, Mercury, Venus, Earth, Moon, Luna, Mars, Jupiter, - Saturn, Uranus, Neptune, Pluto + Saturn, Uranus, Neptune, Pluto, G # Export functions export semimajor_axis, eccentricity, eccentricity_vector, inclination, true_anomoly, periapsis_radius, apoapsis_radius, periapsis_velocity, apoapsis_velocity, - radius, velocity, orbital_period, + radius, velocity, orbital_period, perifocal, inertial, time_since_periapsis, mean_motion, semi_parameter, conic_anomoly, specific_angular_momentum_vector, specific_angular_momentum, specific_energy, isapprox, isequal, TwobodyPropagationResult, kepler, conic, diff --git a/src/TwoBody/kepler.jl b/src/TwoBody/kepler.jl index 87cc8cec..800680a8 100644 --- a/src/TwoBody/kepler.jl +++ b/src/TwoBody/kepler.jl @@ -9,7 +9,7 @@ Solves Kepler's Problem for `orbit` and `Δtᵢ`. """ -function kepler(orbit::T, Δtᵢ::N = orbital_period(orbit); tol=1e-14, max_iter=100) where {T<:Orbit, N<:Number} +function kepler(orbit::Orbit, Δtᵢ::T = orbital_period(orbit); tol=1e-14, max_iter=100) where T<:Unitful.Time conic_section = conic(orbit) @@ -23,7 +23,7 @@ function kepler(orbit::T, Δtᵢ::N = orbital_period(orbit); tol=1e-14, max_iter Δt = Δtᵢ χ₀ = sign(Δt) * √(-orbit.a) * log(ℯ, (-2 * orbit.body.μ / orbit.a * Δt) / - (orbit.r̅ ⋅ orbit.v̅ + (sign(Δt) * √(-orbit.body.μ * orbit.a) * (1 - norm(orbit.r̅) / orbit.a)))) + (orbit.rᵢ ⋅ orbit.vᵢ + (sign(Δt) * √(-orbit.body.μ * orbit.a) * (1 - norm(orbit.rᵢ) / orbit.a)))) elseif conic_section == Parabolic @@ -41,21 +41,21 @@ function kepler(orbit::T, Δtᵢ::N = orbital_period(orbit); tol=1e-14, max_iter # TODO: Compare loop vs. recursion performance here. # There shouldn't be too large of a difference, since this tends # to converge with only a few iterations. - χₙ, r, ψ, C₂, C₃ = χ(χ₀, Δt, orbit.r̅, orbit.v̅, orbit.a, orbit.body.μ, tol=tol, max_iter=max_iter) + χₙ, r, ψ, C₂, C₃ = χ(χ₀, Δt, orbit.rᵢ, orbit.vᵢ, orbit.a, orbit.body.μ, tol=tol, max_iter=max_iter) # Convert to a Orbit - f = 1 - χₙ^2 / norm(orbit.r̅) * C₂ - ḟ = √(orbit.body.μ) / (norm(orbit.r̅) * r) * χₙ * (ψ * C₃ - 1) + f = 1 - χₙ^2 / norm(orbit.rᵢ) * C₂ + ḟ = √(orbit.body.μ) / (norm(orbit.rᵢ) * r) * χₙ * (ψ * C₃ - 1) g = Δt - (χₙ^3 / √(orbit.body.μ)) * C₃ ġ = 1 - (χₙ^2 / r) * C₂ - return Orbit(f * orbit.r̅ + g * orbit.v̅, ḟ * orbit.r̅ + ġ * orbit.v̅, orbit.body) + return Orbit(f * orbit.rᵢ + g * orbit.vᵢ, ḟ * orbit.rᵢ + ġ * orbit.vᵢ, orbit.body) end -function χ(χₙ, Δt, r̅₀, v̅₀, a, μ; iter=1, tol=1e-14, max_iter=100) +function χ(χₙ, Δt, rᵢ₀, vᵢ₀, a, μ; iter=1, tol=1e-14, max_iter=100) - r₀ = norm(r̅₀) + r₀ = norm(rᵢ₀) ψ = upreferred(χₙ^2 / a) if ψ > 1e-6 @@ -70,15 +70,15 @@ function χ(χₙ, Δt, r̅₀, v̅₀, a, μ; iter=1, tol=1e-14, max_iter=100) C₃ = 1.0 / 6.0 end - r = χₙ^2 * C₂ + (r̅₀ ⋅ v̅₀) * χₙ / √(μ) * (1 - ψ*C₃) + r₀ * (1 - ψ * C₂) - χₙ₊₁ = χₙ + ((√(μ) * Δt - χₙ^3 * C₃ - (r̅₀ ⋅ v̅₀) / √(μ) * χₙ^2 * C₂ - r₀ * χₙ * (1 - ψ * C₃)) / r) + r = χₙ^2 * C₂ + (rᵢ₀ ⋅ vᵢ₀) * χₙ / √(μ) * (1 - ψ*C₃) + r₀ * (1 - ψ * C₂) + χₙ₊₁ = χₙ + ((√(μ) * Δt - χₙ^3 * C₃ - (rᵢ₀ ⋅ vᵢ₀) / √(μ) * χₙ^2 * C₂ - r₀ * χₙ * (1 - ψ * C₃)) / r) if iter > max_iter return NaN, NaN, NaN, NaN, NaN elseif abs(χₙ₊₁ - χₙ) < oneunit(χₙ) * tol return χₙ, r, ψ, C₂, C₃ else - return χ(χₙ₊₁, Δt, r̅₀, v̅₀, a, μ; iter=iter+1, tol=tol, max_iter=max_iter) + return χ(χₙ₊₁, Δt, rᵢ₀, vᵢ₀, a, μ; iter=iter+1, tol=tol, max_iter=max_iter) end end \ No newline at end of file diff --git a/src/TwoBody/twobody_calculations.jl b/src/TwoBody/twobody_calculations.jl index 995bc053..282ed537 100644 --- a/src/TwoBody/twobody_calculations.jl +++ b/src/TwoBody/twobody_calculations.jl @@ -28,18 +28,33 @@ end conic(orbit::Orbit) = conic(eccentricity(orbit)) """ - Orbit(r̅, v̅, body) + Orbit(rᵢ, vᵢ, body) Construct `Orbit` from Cartesian elements. """ -function Orbit(r̅, v̅, body) - - - return Orbit{conic(eccentricity(r̅, v̅, body.μ))}( - SVector{3}(Float64.(r̅)), - SVector{3}(Float64.(v̅)), - orbital_elements(r̅, v̅, body)..., - body) +function Orbit(rᵢ, vᵢ, body) + + e, a, i, Ω, ω, ν = orbital_elements(rᵢ, vᵢ, body) + rₚ = perifocal(i,Ω,ν,rᵢ) + vₚ = perifocal(i,Ω,ν,vᵢ) + return Orbit{ + conic(eccentricity(rᵢ, vᵢ, body.μ)), + Float64, + eltype(rᵢ), + eltype(vᵢ), + eltype(rₚ), + eltype(vₚ), + typeof(a), + typeof(i), + typeof(Ω), + typeof(ω), + typeof(ν) + }(SVector{3}(Float64.(rᵢ)), + SVector{3}(Float64.(vᵢ)), + SVector{3}(Float64.(rₚ)), + SVector{3}(Float64.(vₚ)), + map(Float64, [e,a,i,Ω,ω,ν])..., + body) end @@ -50,22 +65,37 @@ Construct `Orbit` from Keplerian elements. """ function Orbit(e, a, i, Ω, ω, ν, body) - r̅, v̅ = cartesian(e, a, i, Ω, ω, ν, body) - return Orbit{conic(e)}( - SVector{3}(Float64.(r̅)), - SVector{3}(Float64.(v̅)), - map(Float64, [e,a,i,Ω,ω,ν])..., - body) + rᵢ, vᵢ = cartesian(e, a, i, Ω, ω, ν, body) + rₚ = perifocal(i,Ω,ν,rᵢ) + vₚ = perifocal(i,Ω,ν,vᵢ) + return Orbit{ + conic(e), + Float64, + eltype(rᵢ), + eltype(vᵢ), + eltype(rₚ), + eltype(vₚ), + typeof(a), + typeof(i), + typeof(Ω), + typeof(ω), + typeof(ν) + }(SVector{3}(Float64.(rᵢ)), + SVector{3}(Float64.(vᵢ)), + SVector{3}(rₚ), + SVector{3}(vₚ), + map(Float64, [e,a,i,Ω,ω,ν])..., + body) end """ - orbital_elements(r̅, v̅, body::CelestialBody) + orbital_elements(rᵢ, vᵢ, body::CelestialBody) Returns a Keplarian representation of a Cartesian orbital state. Algorithm taught in ENAE601. """ -function orbital_elements(r̅, v̅, μ) +function orbital_elements(rᵢ, vᵢ, μ) î = SVector{3, Float64}([1, 0, 0]) ĵ = SVector{3, Float64}([0, 1, 0]) @@ -75,10 +105,10 @@ function orbital_elements(r̅, v̅, μ) val ≈ -1.0 ? acos(un, -1.0) : acos(un, val) - h̅ = specific_angular_momentum_vector(r̅, v̅) - a = semimajor_axis(norm(r̅), norm(v̅), μ) - n̅ = k̂ × specific_angular_momentum_vector(r̅, v̅) - e̅ = eccentricity_vector(r̅, v̅, μ) + h̅ = specific_angular_momentum_vector(rᵢ, vᵢ) + a = semimajor_axis(norm(rᵢ), norm(vᵢ), μ) + n̅ = k̂ × specific_angular_momentum_vector(rᵢ, vᵢ) + e̅ = eccentricity_vector(rᵢ, vᵢ, μ) e = norm(e̅) i = acos_chop(u"rad", (h̅ ⋅ k̂) / norm(h̅)) @@ -90,22 +120,24 @@ function orbital_elements(r̅, v̅, μ) acos_chop(u"rad", (n̅ ⋅ e̅) / (norm(n̅) * e)) : 2π * u"rad" - acos_chop(u"rad", (n̅ ⋅ e̅) / (norm(n̅) * e)) - ν = ustrip(r̅ ⋅ v̅) > 0 ? - acos_chop(u"rad", (e̅ ⋅ r̅) / (e * norm(r̅))) : - 2π * u"rad" - acos_chop(u"rad", (e̅ ⋅ r̅) / (e * norm(r̅))) + ν = ustrip(rᵢ ⋅ vᵢ) > 0 ? + acos_chop(u"rad", (e̅ ⋅ rᵢ) / (e * norm(rᵢ))) : + 2π * u"rad" - acos_chop(u"rad", (e̅ ⋅ rᵢ) / (e * norm(rᵢ))) return e, uconvert(u"km", a), uconvert(u"°", i), uconvert(u"°", Ω), uconvert(u"°", ω), uconvert(u"°", ν) end -orbital_elements(r̅, v̅, body::CelestialBody) = orbital_elements(r̅, v̅, body.μ) - +orbital_elements(rᵢ, vᵢ, body::CelestialBody) = orbital_elements(rᵢ, vᵢ, body.μ) +orbital_elements(orbit::Orbit) = orbit.e, orbit.a, orbit.i, + orbit.Ω, orbit.ω, orbit.ν """ cartesian(e, a, i, Ω, ω, ν, μ) -Returns a Cartesian representation of a Keplerian two-body orbital state. +Returns a Cartesian representation of a Keplerian two-body orbital state +in an inertial frame, centered at the center of mass of the central body. Algorithm taught in ENAE601. """ function cartesian(e, a, i, Ω, ω, ν, μ) @@ -122,8 +154,23 @@ function cartesian(e, a, i, Ω, ω, ν, μ) Ŵ=SVector{3, Float64}([0, 0, 1]) # Find state in Perifocal frame - r̅ₚ = (r * cos(ν) .* P̂ .+ r * sin(ν) .* Q̂) - v̅ₚ = √(μ/p) * ((-sin(ν) * P̂) .+ ((e + cos(ν)) .* Q̂)) + rₚ = (r * cos(ν) .* P̂ .+ r * sin(ν) .* Q̂) + vₚ = √(μ/p) * ((-sin(ν) * P̂) .+ ((e + cos(ν)) .* Q̂)) + + return uconvert.(u"km", inertial(i,Ω,ω,rₚ)), + uconvert.(u"km/s", inertial(i,Ω,ω,vₚ)) + +end +cartesian(e, a, i, Ω, ω, ν, body::CelestialBody) = cartesian(e, a, i, Ω, ω, ν, body.μ) +cartesian(orbit::Orbit) = orbit.rᵢ, orbit.vᵢ + +""" + inertial(i, Ω, ω, vec₃) + inertial(orbit::Orbit) + +Transforms 3-vector from Perifocal frame to Cartesian space (x,y,z). +""" +function inertial(i, Ω, ω, vec₃) # Set up Perifocal ⟶ Cartesian conversion R_3Ω = SMatrix{3,3,Float64}( @@ -139,13 +186,41 @@ function cartesian(e, a, i, Ω, ω, ν, μ) -sin(ω) cos(ω) 0. 0. 0. 1.]) - ᴵTₚ = (R_3ω * R_1i * R_3Ω)' + ᴵTₚ = transpose(R_3ω * R_1i * R_3Ω) - return uconvert.(u"km", ᴵTₚ * r̅ₚ), uconvert.(u"km/s", ᴵTₚ * v̅ₚ) + return ᴵTₚ * vec₃ end -cartesian(e, a, i, Ω, ω, ν, body::CelestialBody) = cartesian(e, a, i, Ω, ω, ν, body.μ) +inertial(orbit::Orbit) = orbit.rᵢ, orbit.vᵢ + +""" + perifocal(i, Ω, ω, vec₃) + perifocal(orbit::Orbit) + +Transforms 3-vector from Cartesian frame to Perifocal frame. +""" +function perifocal(i, Ω, ω, vec₃) + # Set up Perifocal ⟶ Cartesian conversion + R_3Ω = SMatrix{3,3,Float64}( + [cos(Ω) sin(Ω) 0.; + -sin(Ω) cos(Ω) 0.; + 0. 0. 1.]) + R_1i = SMatrix{3,3,Float64}( + [1. 0. 0.; + 0. cos(i) sin(i); + 0. -sin(i) cos(i)]) + R_3ω = SMatrix{3,3,Float64}( + [cos(ω) sin(ω) 0. + -sin(ω) cos(ω) 0. + 0. 0. 1.]) + + ᵖTᵢ = R_3ω * R_1i * R_3Ω + + return ᵖTᵢ * vec₃ + +end +perifocal(orbit::Orbit) = orbit.rₚ, orbit.vₚ """ semimajor_axis(r, v, μ) @@ -161,27 +236,27 @@ end semimajor_axis(orbit::Orbit) = orbit.a """ - specific_angular_momentum_vector(r̅, v̅) + specific_angular_momentum_vector(rᵢ, vᵢ) specific_angular_momentum_vector(orbit::Orbit) Returns specific angular momentum vector, h̅. """ -function specific_angular_momentum_vector(r̅, v̅) +function specific_angular_momentum_vector(rᵢ, vᵢ) - return r̅ × v̅ + return rᵢ × vᵢ end specific_angular_momentum_vector(orbit::Orbit) = - specific_angular_momentum_vector(orbit.r̅, orbit.v̅) + specific_angular_momentum_vector(orbit.rᵢ, orbit.vᵢ) """ - specific_angular_momentum(r̅, v̅) + specific_angular_momentum(rᵢ, vᵢ) specific_angular_momentum(orbit::Orbit) Returns scalar specific angular momentum vector, h. """ -specific_angular_momentum(r̅, v̅) = norm(specific_angular_momentum_vector(r̅, v̅)) -specific_angular_momentum(orbit::Orbit) = specific_angular_momentum(orbit.r̅, orbit.v̅) +specific_angular_momentum(rᵢ, vᵢ) = norm(specific_angular_momentum_vector(rᵢ, vᵢ)) +specific_angular_momentum(orbit::Orbit) = specific_angular_momentum(orbit.rᵢ, orbit.vᵢ) """ specific_energy(a, μ) @@ -195,25 +270,25 @@ specific_energy(r, v, μ) = (v^2 / 2) - (μ / r) specific_energy(orbit::Orbit) = specific_energy(orbit.a, orbit.body.μ) """ - eccentricity_vector(r̅, v̅, μ) + eccentricity_vector(rᵢ, vᵢ, μ) eccentricity_vector(orbit::Orbit) Returns orbital eccentricity vector e̅. """ -function eccentricity_vector(r̅, v̅, μ) +function eccentricity_vector(rᵢ, vᵢ, μ) - return (1 / μ) * ((v̅ × specific_angular_momentum_vector(r̅, v̅)) - μ * r̅ / norm(r̅)) + return (1 / μ) * ((vᵢ × specific_angular_momentum_vector(rᵢ, vᵢ)) - μ * rᵢ / norm(rᵢ)) end -eccentricity_vector(orbit::Orbit) = eccentricity_vector(orbit.r̅, orbit.v̅, orbit.body.μ) +eccentricity_vector(orbit::Orbit) = eccentricity_vector(orbit.rᵢ, orbit.vᵢ, orbit.body.μ) """ - eccentricity(r̅, v̅, μ) + eccentricity(rᵢ, vᵢ, μ) eccentricity(orbit::Orbit) Returns orbital eccentricity, e. """ -eccentricity(r̅, v̅, μ) = norm(eccentricity_vector(r̅, v̅, μ)) +eccentricity(rᵢ, vᵢ, μ) = norm(eccentricity_vector(rᵢ, vᵢ, μ)) eccentricity(orbit::Orbit) = orbit.e """ @@ -247,7 +322,7 @@ velocity(orbit::Orbit) = velocity(radius(orbit), orbit.a, orbit.body.μ) periapsis_radius(a, e) periapsis_radius(orbit::Orbit) -Returns periapsis radius, r̅_p. +Returns periapsis radius, rᵢ_p. """ periapsis_radius(a, e) = a * (1 - e) periapsis_radius(orbit::Orbit) = periapsis_radius(orbit.a, orbit.e) @@ -378,8 +453,8 @@ Returns true if all elements in each system are within `atol` of the other. """ function Base.isapprox(c1::Orbit, c2::Orbit; atol=1e-8) - return all(ustrip.(c1.r̅ - c2.r̅) .< atol) && - all(ustrip.(c1.r̅ - c2.r̅) .< atol) && + return all(ustrip.(c1.rᵢ - c2.rᵢ) .< atol) && + all(ustrip.(c1.rᵢ - c2.rᵢ) .< atol) && ustrip(upreferred(c1.e - c2.e)) .< atol && ustrip(upreferred(c1.a - c2.a)) .< atol && ustrip(upreferred(mod(c1.i, 180u"°") - mod(c2.i, 180u"°"))) .< atol && @@ -397,8 +472,8 @@ Returns true if all elements of each system are identically equal. """ function Base.isequal(c1::Orbit, c2::Orbit) - return all(c1.r̅ .== c2.r̅) && - all(c1.v̅ .== c2.v̅) && + return all(c1.rᵢ .== c2.rᵢ) && + all(c1.vᵢ .== c2.vᵢ) && c1.e == c2.e && c1.a == c2.a && mod(c1.i, 180u"°") == mod(c2.i, 180u"°") && diff --git a/src/TwoBody/twobody_states.jl b/src/TwoBody/twobody_states.jl index c9bf0524..b0bc0ab8 100644 --- a/src/TwoBody/twobody_states.jl +++ b/src/TwoBody/twobody_states.jl @@ -17,7 +17,7 @@ abstract type AbstractConic end Abstract type for all two-body orbital representations. """ -abstract type TwoBodySystem{T<:AbstractConic} <: OrbitalSystem end +abstract type TwoBodySystem{C<:AbstractConic} <: OrbitalSystem end """ @@ -69,8 +69,8 @@ struct CelestialBody m::Quantity R::Quantity μ::Quantity + CelestialBody(m, R) = new(m, R, G * m) end -CelestialBody(m, R) = CelestialBody(m, R, G * m) # All data pulled from the following references: @@ -116,34 +116,106 @@ Pluto = CelestialBody( Struct for storing TwoBody orbital states for all conics. """ -struct Orbit{T<:AbstractConic} <: TwoBodySystem{T} +struct Orbit{ + C <: AbstractConic, + F <: AbstractFloat, + R <: Unitful.Length{F}, + V <: Unitful.Velocity{F}, + RP <: Unitful.Length{F}, + VP <: Unitful.Velocity{F}, + A <: Unitful.Length{F}, + I <: Unitful.DimensionlessQuantity{F}, + O <: Unitful.DimensionlessQuantity{F}, + W <: Unitful.DimensionlessQuantity{F}, + N <: Unitful.DimensionlessQuantity{F} + } <: TwoBodySystem{C} # Cartesian representation - r̅::SVector{3, Unitful.Length{Float64}} - v̅::SVector{3, Unitful.Velocity{Float64}} + rᵢ::SVector{3, R} + vᵢ::SVector{3, V} + + # Perifocal (in-orbital-plane) representation + rₚ::SVector{3, RP} + vₚ::SVector{3, VP} # Keplerian representation - e::Union{Float64,Unitful.DimensionlessQuantity{Float64}} - a::Unitful.Length{Float64} - i::Unitful.DimensionlessQuantity{Float64} - Ω::Unitful.DimensionlessQuantity{Float64} - ω::Unitful.DimensionlessQuantity{Float64} - ν::Unitful.DimensionlessQuantity{Float64} + e::F + a::A + i::I + Ω::O + ω::W + ν::N # Body body::CelestialBody end +""" + show(io::IO, orbit::Orbit) + +Overloads Base.show() for ::Orbit instances. +""" +function Base.show(io::IO, orbit::Orbit) + + println(io, crayon"green", conic(orbit), " Two Body Orbit:") + println(io, "") + + println(io, crayon"cyan", " Position (inertial): [", + ustrip(u"km", orbit.rᵢ[1]), ", ", + ustrip(u"km", orbit.rᵢ[2]), ", ", + ustrip(u"km", orbit.rᵢ[3]), "] ", u"km") + println(io, crayon"cyan", " Velocity (inertial): [", + ustrip(u"km/s", orbit.vᵢ[1]), ", ", + ustrip(u"km/s", orbit.vᵢ[2]), ", ", + ustrip(u"km/s", orbit.vᵢ[3]), "] ", u"km/s") + + println(io, "") + println(io, crayon"blue", " Position (perifocal): [", + round(ustrip(u"km", orbit.rₚ[1]), digits=6), ", ", + round(ustrip(u"km", orbit.rₚ[2]), digits=6), ", ", + round(ustrip(u"km", orbit.rₚ[3]), digits=6), "] ", u"km/s") + println(io, crayon"blue", " Velocity (perifocal): [", + round(ustrip(u"km/s", orbit.vₚ[1]), digits=6), ", ", + round(ustrip(u"km/s", orbit.vₚ[2]), digits=6), ", ", + round(ustrip(u"km/s", orbit.vₚ[3]), digits=6), "] ", u"km/s") + + println(io, "") + println(io, crayon"light_magenta", + " Eccentricity: ", + orbit.e) + println(io, crayon"light_magenta", + " Semimajor Axis: ", + ustrip(u"km", orbit.a), " ", u"km") + println(io, crayon"light_magenta", + " Inclination: ", + ustrip(u"°", orbit.i), u"°") + println(io, crayon"light_magenta", + " RAAN: ", + ustrip(u"°", orbit.Ω), u"°") + println(io, crayon"light_magenta", + " Arg. Periapsis: ", + ustrip(u"°", orbit.ω), u"°") + println(io, crayon"light_magenta", + " True Anomoly: ", + ustrip(u"°", orbit.ν), u"°") + + println(io, "") + println(io, crayon"magenta", + " Body (μ): ", + ustrip(u"km^3 / s^2", orbit.body.μ), " ", u"km^3/s^2") +end + """ InvalidOrbit(body::CelestialBody) Returns a `Orbit` with `NaN` state values. Used by `propagate_twobody` and `kepler` to indicate failed convergance. """ -InvalidOrbit(body::CelestialBody) = Orbit(SVector{3}(NaN * u"km", NaN * u"km", NaN * u"km"), - SVector{3}(NaN * u"km", NaN * u"km", NaN * u"km"), - body) +InvalidOrbit(body::CelestialBody) = Orbit( + SVector{3}(NaN * u"km", NaN * u"km", NaN * u"km"), + SVector{3}(NaN * u"km/s", NaN * u"km/s", NaN * u"km/s"), + NaN * u"km", NaN * u"km/s", body) """ isinvalid(orbit::Orbit) @@ -151,4 +223,4 @@ InvalidOrbit(body::CelestialBody) = Orbit(SVector{3}(NaN * u"km", NaN * u"km", N Checks for `NaN` valued orbital states, which are used to indicate an invalid `Orbit`. """ -isinvalid(orbit::Orbit) = all(map(x->!isnan(getfield(orbit, x)), [:r̅, :v̅, :e, :a, :i, :Ω, :ω, :ν])) \ No newline at end of file +isinvalid(orbit::Orbit) = all(map(x->!isnan(getfield(orbit, x)), [:rᵢ, :vᵢ, :e, :a, :i, :Ω, :ω, :ν])) \ No newline at end of file diff --git a/test/TwoBody/test_twobody.jl b/test/TwoBody/test_twobody.jl index 894564ea..6d456f8b 100644 --- a/test/TwoBody/test_twobody.jl +++ b/test/TwoBody/test_twobody.jl @@ -5,9 +5,9 @@ using UnitfulAstrodynamics @testset "Transformations" begin - r̅ = [0.0, 11681.0, 0.0] * u"km" - v̅ = [5.134, 4.226, 2.787] * u"km/s" - orbit = Orbit(r̅, v̅, Earth) + rᵢ = [0.0, 11681.0, 0.0] * u"km" + vᵢ = [5.134, 4.226, 2.787] * u"km/s" + orbit = Orbit(rᵢ, vᵢ, Earth) @test orbit.a ≈ 24509.272364065997 * u"km" @test orbit.e ≈ 0.7234527725236475 @@ -16,7 +16,7 @@ using UnitfulAstrodynamics @test Orbit(map(x->getfield(orbit, x), [:e,:a, :i, :Ω, :ω, :ν])..., orbit.body) ≈ orbit - e = 0.3 * u"rad" + e = 0.3 a = 15000. * u"km" + 1.0u"Rearth" i = 10. * u"°" Ω = 0. * u"°" @@ -24,15 +24,15 @@ using UnitfulAstrodynamics ν = 0. * u"°" orbit = Orbit(e, a, i, Ω, ω, ν, Earth) - @test isapprox(orbit, Orbit(orbit.r̅, orbit.v̅, orbit.body), atol=1e-6) + @test isapprox(orbit, Orbit(orbit.rᵢ, orbit.vᵢ, orbit.body), atol=1e-6) end @testset "Kepler" begin - r̅ = [0.0, 11681.0, 0.0]u"km" - v̅ = [5.134, 4.226, 2.787]u"km/s" - orbit = Orbit(r̅, v̅, Earth) + rᵢ = [0.0, 11681.0, 0.0]u"km" + vᵢ = [5.134, 4.226, 2.787]u"km/s" + orbit = Orbit(rᵢ, vᵢ, Earth) @test kepler(orbit, orbital_period(orbit)) ≈ orbit From aad99c56ae791244f0fd103b6bb08e600a87c941 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Thu, 15 Oct 2020 18:56:08 -0400 Subject: [PATCH 02/12] Moving documentation into tag.yml --- .github/workflows/tag.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index c13ec18d..aabb980c 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -1,12 +1,23 @@ -name: TagBot +name: Documentation on: schedule: - cron: 0 0 * * * workflow_dispatch: jobs: TagBot: + name: TagBot runs-on: ubuntu-latest steps: - uses: JuliaRegistries/TagBot@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + Documenter: + name: Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-docdeploy@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} From 1e75cfdab59d5691c1f265728f54e6287a7a2415 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Thu, 15 Oct 2020 18:56:21 -0400 Subject: [PATCH 03/12] Delete docs.yml --- .github/workflows/docs.yml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 46718e17..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Documentation - -on: - push: - branches: - - main - tags: '*' - -jobs: - Documenter: - name: Documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: julia-actions/julia-buildpkg@latest - - uses: julia-actions/julia-docdeploy@latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} From 73e133d04dcc6dd217f353c458838d4388f5edfc Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 10:45:32 -0400 Subject: [PATCH 04/12] Adding documentation for release 0.6 --- README.md | 8 +- docs/make.jl | 6 +- docs/src/Overview/contents.md | 43 ++++++++++ docs/src/Overview/usage.md | 127 ---------------------------- docs/src/TwoBody/functions.md | 6 +- docs/src/index.md | 121 ++++++++++++++++++++------ src/TwoBody/TwoBody.jl | 2 +- src/TwoBody/twobody_calculations.jl | 12 +-- 8 files changed, 158 insertions(+), 167 deletions(-) create mode 100644 docs/src/Overview/contents.md delete mode 100644 docs/src/Overview/usage.md diff --git a/README.md b/README.md index 91bf1d50..2c6cd9f2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ [![Tests](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Tests/badge.svg)](https://github.com/cadojo/UnitfulAstrodynamics.jl/actions?query=workflow%3ATests) -[![Docs](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Documentation/badge.svg)](https://cadojo.github.io/UnitfulAstrodynamics.jl/stable) +[![Docs](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Documentation/badge.svg)](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev) # UnitfulAstrodynamics.jl A simple Astrodynamics package, written with Julia! ## Motivation -This package aims to provide a simple interface for common astrodynamics problems. It was created to learn more about Astrodynamics, and will be developed alongside a Graduate Astrodynamics course at the University of Maryland. The packages [JuliaSpace/Astrodynamics.jl](https://github.com/JuliaSpace/Astrodynamics.jl) [JuliaAstro/AstroBase.jl](https://github.com/JuliaAstro/AstroBase.jl)are more fully featured. I will continue adding features to this package, but for a more complete feature set, use the packages provided by [JuliaSpace](https://github.com/JuliaSpace) and [JuliaAstro](https://github.com/JuliaAstro). +This package aims to provide a simple interface for common astrodynamics problems. It was created to learn more about Astrodynamics, and will be developed alongside a Graduate Astrodynamics course at the University of Maryland. The packages [JuliaSpace/Astrodynamics.jl](https://github.com/JuliaSpace/Astrodynamics.jl) and [JuliaAstro/AstroBase.jl](https://github.com/JuliaAstro/AstroBase.jl) are more fully featured. I will continue adding features to this package, but for a more complete feature set, use the packages provided by [JuliaSpace](https://github.com/JuliaSpace) and [JuliaAstro](https://github.com/JuliaAstro). ## Credits @@ -13,13 +13,13 @@ This package aims to provide a simple interface for common astrodynamics problem * All equations and algorithms within `UnitfulAstrodynamics` are pulled from Vallado's _Fundamentals of Astrodynamics and Applications_, as well as course notes from ENAE 601 (Astrodynamics) at the University of Maryland. \[2\] [JuliaAstro/AstroBase.jl](https://github.com/JuliaAstro/AstroBase.jl) -* `AstroBase` is referenced as a well thought-out Julia package structure example (I'm new to Julia!), as well as feature ideas. +* `AstroBase` is referenced as a well thought-out Julia package structure example, as well as feature ideas. \[3\] [Unitful.jl](https://github.com/PainterQubits/Unitful.jl) and [UnitfulAstro.jl](https://github.com/JuliaAstro/UnitfulAstro.jl) are used for unit handling. ## Usage -Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/stable/Overview/usage/#Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! +Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev/Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! #### Two-body Problem diff --git a/docs/make.jl b/docs/make.jl index eb0076e7..a79c1807 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -6,10 +6,10 @@ makedocs(modules=[UnitfulAstrodynamics], format=Documenter.HTML(), sitename="UnitfulAstrodynamics.jl", pages=[ - "Home" => "index.md", - "Overview" => Any[ + "Getting Started" => "index.md", + "Index" => Any[ "About" => "Overview/about.md", - "Usage" => "Overview/usage.md" + "Table of Contents" => "Overview/contents.md" ], "`TwoBody`" => Any[ "Data Structures and Types" => "TwoBody/types.md", diff --git a/docs/src/Overview/contents.md b/docs/src/Overview/contents.md new file mode 100644 index 00000000..fc6828a4 --- /dev/null +++ b/docs/src/Overview/contents.md @@ -0,0 +1,43 @@ +## Table of Contents + +### Index + +```@contents +Pages = ["Overview/about.md", "Overview/usage.md"] +Depth = 3 +``` + +### TwoBody + +```@contents +Pages = ["TwoBody/types.md", "TwoBody/functions.md"] +Depth = 3 +``` + +### NBody + +```@contents +Pages = ["NBody/types.md", "NBody/functions.md"] +Depth = 3 +``` + +### Propagators + +```@contents +Pages = ["Propagators/types.md", "Propagators/functions.md"] +Depth = 3 +``` + +### Plots + +```@contents +Pages = ["Plots/functions.md"] +Depth = 3 +``` + +### Common Abstract Types + +```@contents +Pages = ["AbstractTypes/types.md"] +Depth = 3 +``` diff --git a/docs/src/Overview/usage.md b/docs/src/Overview/usage.md deleted file mode 100644 index 94c03e1c..00000000 --- a/docs/src/Overview/usage.md +++ /dev/null @@ -1,127 +0,0 @@ -## Getting Started - -### Units are Required! - -Currently, `Astrodynamics.jl` `reexport`'s `Unitful`, `UnitfulAstro`, and `UnitfulAngles`. Units are required for all `TwoBody` and `NBody` computations. In the future, I'd like to make units optional. - -### Two-body Problem - -The `TwoBody` module handles Astrodynamics scenarios within the two-body problem. You can make a `Orbit` by specifying a `CelestialBody` (Sun, Earth, Moon, Mars, etc.), and a Cartesian or Keplerian state. - -```Julia -# Cartesian state to Orbit -r̅ = [0.0, 11681.0, 0.0]u"km" -v̅ = [5.134, 4.226, 2.787]u"km/s" -orbit1 = Orbit(r̅, v̅, Earth) - -# Keplerian state to Orbit -e = 0.3 * u"rad" -a = 15000 * u"km" + Earth.R -i = 10 * u"°" -Ω = 0 * u"°" -ω = 10 * u"°" -ν = 0 * u"°" -orbit2 = Orbit(e, a, i, Ω, ω, ν, Earth) - -# This is a true fact! -orbit1 ≈ orbit2 - -# For the rest of this section... -orbit = orbit1 -``` - -Now you can solve __Kepler's Prediction Problem__, __propagate__ the satellite's trajectory over a specified intervol in time, and __plot__ the resultant trajectory with `Plots.jl`. - -```Julia -# Kepler's Prediction problem -orbit_later = kepler(orbit, orbital_period(orbit)) - -# Orbit propagation -sols = propagate(orbit, orbital_period(orbit)) - -# Plotting (with Plots.jl kwargs) -plot3d(sols; title="Plots.jl keywords work!", xlabel="Woo") - -# Another true fact! -sols.step[end] ≈ orbit_later -``` - -You may have noticed the `orbital_period` function. All common two-body problem equations have been included as functions with common arguments,`orbital_period(a, μ)`, and with `Astrodynamics.jl` structure arguments, `orbital_period(orbit)`. The current list of supported functions is shown below, and is described in [`TwoBody` Calculations](@ref). - -```Julia -# Look at ~all~ those functions -semimajor_axis -eccentricity -eccentricity_vector -inclination -true_anomoly, -periapsis_radius -apoapsis_radius -periapsis_velocity -apoapsis_velocity, -radius -radius_vector -velocity -velocity_vector -orbital_period -time_since_periapsis -mean_motion -semi_parameter -conic_anomoly -specific_angular_momentum -specific_angular_momentum_vector -specific_energy -``` - -Not sure how to use one of those? Check the docstrings in Julia's REPL! - -```Julia -help?> eccentricity -search: eccentricity eccentricity_vector - - eccentricity(r̅, v̅, μ) - eccentricity(orbit::Orbit) - - Returns orbital eccentricity, e. -``` - -### NBody - -The `NBody` module helps to solve the classical gravitational `NBody` problem. This is the baby version - point mass bodies, and no relativity. But it's still useful! - -You can make your own `Body` by specifying an initial Cartesian state, and a mass. - -```Julia -# It's MY Earth, and I want it now -r̅₁ = [0.0, 0.0, 0.0]u"km" -v̅₁ = [0.0, 0.0, 0.0]u"km/s" -m₁ = Earth.m -myEarth = Body(r̅₁, v̅₁, m₁) - -# And we'll need a satellite... -r̅₂ = [0.0, 11681.0, 0.0]u"km" -v̅₂ = [5.134, 4.226, 2.787]u"km/s" -m₂ = 1000.0u"kg" -mySatellite = Body(r̅₂, v̅₂, m₂) -``` - -A `MultibodySystem` contains an array of `Bodies`. - -```Julia -# Construct a MultibodySystem -sys = MultibodySystem([myEarth, mySatellite]) -``` - -And you can __propagate__ a `MultibodySystem` through time to numerically find the final states for each `Body`. The package `DifferentialEquations.jl` is used for the numerical integration. For all __propagation__ functions in `Astrodynamics.jl`, you can specify `kwargs` as you would for a `DifferentialEquations.jl` `solve` call. - -```Julia -# Propagate n-body system -sols = propagate(sys, 10000u"s"; abstol=1e-14, reltol=1e-14) -``` - -As with a two-body `Orbit`, you can also plot each timestep in the n-body propagation. - -```Julia -# Plot n-body propagation results -plot3d(sols; title="Plots.jl keywords work!", xlabel="Woo") -``` \ No newline at end of file diff --git a/docs/src/TwoBody/functions.md b/docs/src/TwoBody/functions.md index 2c4e1f0c..5870dc0e 100644 --- a/docs/src/TwoBody/functions.md +++ b/docs/src/TwoBody/functions.md @@ -5,11 +5,13 @@ Often, these functions are provided with common arguments (such as `orbital_peri ## Orbital Representations -You can convert between Cartesian and Keplerian `TwoBody` orbital representations by using [`cartesian`](@ref) and [`orbital_elements`](@ref). +You can convert between Cartesian and Keplerian `TwoBody` orbital representations by using [`cartesian`](@ref) and [`keplerian`](@ref). ```@docs cartesian -orbital_elements +keplerian +inertial +perifocal ``` ## Kepler's Prediction Problem diff --git a/docs/src/index.md b/docs/src/index.md index e657fc41..023f9f52 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,43 +1,116 @@ # UnitfulAstrodynamics.jl Documentation -## Overview +## Getting Started -```@contents -Pages = ["Overview/about.md", "Overview/usage.md"] -Depth = 3 +### Installation + +`UnitfulAstrodynamics` is included in Julia's General package registry. + +```Julia +# In Julia's REPL +]add UnitfulAstrodynamics + +# Or, with `Pkg` +Pkg.add("UnitfulAstrodynamics") ``` -## TwoBody +### Units are Required! + +`UnitfulAstrodynamics.jl` uses `Reexport.jl` to expose `Unitful`, `UnitfulAstro`, and `UnitfulAngles`. Units are required for all `TwoBody` and `NBody` computations, and all required types in `Unitful`, `UnitfulAstro`, and `UnitfulAngles` are included _with_ `UnitfulAstrodynamics` when you call `using UnitfulAstrodynamics`. + +### Two-body Problem + +The `TwoBody` module handles Astrodynamics scenarios within the two-body problem. You can make a `Orbit` by specifying a `CelestialBody` (Sun, Earth, Moon, Mars, etc.), and a Cartesian or Keplerian state. -```@contents -Pages = ["TwoBody/types.md", "TwoBody/functions.md"] -Depth = 3 +```Julia +# Cartesian state to Orbit +r̅ = [0.0, 11681.0, 0.0]u"km" +v̅ = [5.134, 4.226, 2.787]u"km/s" +orbit1 = Orbit(r̅, v̅, Earth) + +# Keplerian state to Orbit +e = 0.3 * u"rad" +a = 15000 * u"km" + Earth.R +i = 10 * u"°" +Ω = 0 * u"°" +ω = 10 * u"°" +ν = 0 * u"°" +orbit2 = Orbit(e, a, i, Ω, ω, ν, Earth) + +# This is a true fact! +orbit1 ≈ orbit2 + +# For the rest of this section... +orbit = orbit1 ``` -## NBody +Now you can solve __Kepler's Prediction Problem__, __propagate__ the satellite's trajectory over a specified intervol in time, and __plot__ the resultant trajectory with `Plots.jl`. + +```Julia +# Kepler's Prediction problem +orbit_later = kepler(orbit, orbital_period(orbit)) + +# Orbit propagation +sols = propagate(orbit, orbital_period(orbit)) + +# Plotting (with Plots.jl kwargs) +plot3d(sols; title="Plots.jl keywords work!", xlabel="Woo") -```@contents -Pages = ["NBody/types.md", "NBody/functions.md"] -Depth = 3 +# Another true fact! +sols.step[end] ≈ orbit_later ``` -## Propagators +You may have noticed the `orbital_period` function. All common two-body problem equations have been included as functions with common arguments,`orbital_period(a, μ)`, and with `Astrodynamics.jl` structure arguments, `orbital_period(orbit)`. The current list of supported functions is described in [`TwoBody` Calculations](@ref). -```@contents -Pages = ["Propagators/types.md", "Propagators/functions.md"] -Depth = 3 +Not sure how to use one of those helper functions? Check the docstrings in Julia's REPL! + +```Julia +help?> eccentricity +search: eccentricity eccentricity_vector + + eccentricity(r̅, v̅, μ) + eccentricity(orbit::Orbit) + + Returns orbital eccentricity, e. ``` -## Plots +### NBody + +The `NBody` module helps to solve the classical gravitational `NBody` problem. This is the baby version - point mass bodies, and no relativity. But it's still useful! + +You can make your own `Body` by specifying an initial Cartesian state, and a mass. + +```Julia +# It's MY Earth, and I want it now +r̅₁ = [0.0, 0.0, 0.0]u"km" +v̅₁ = [0.0, 0.0, 0.0]u"km/s" +m₁ = Earth.m +myEarth = Body(r̅₁, v̅₁, m₁) -```@contents -Pages = ["Plots/functions.md"] -Depth = 3 +# And we'll need a satellite... +r̅₂ = [0.0, 11681.0, 0.0]u"km" +v̅₂ = [5.134, 4.226, 2.787]u"km/s" +m₂ = 1000.0u"kg" +mySatellite = Body(r̅₂, v̅₂, m₂) ``` -## Common Abstract Types +A `MultibodySystem` contains an array of `Bodies`. -```@contents -Pages = ["AbstractTypes/types.md"] -Depth = 3 +```Julia +# Construct a MultibodySystem +sys = MultibodySystem([myEarth, mySatellite]) ``` + +And you can __propagate__ a `MultibodySystem` through time to numerically find the final states for each `Body`. The package `DifferentialEquations.jl` is used for the numerical integration. For all __propagation__ functions in `Astrodynamics.jl`, you can specify `kwargs` as you would for a `DifferentialEquations.jl` `solve` call. + +```Julia +# Propagate n-body system +sols = propagate(sys, 10000u"s"; abstol=1e-14, reltol=1e-14) +``` + +As with a two-body `Orbit`, you can also plot each timestep in the n-body propagation. + +```Julia +# Plot n-body propagation results +plot3d(sols; title="Plots.jl keywords work!", xlabel="Woo") +``` \ No newline at end of file diff --git a/src/TwoBody/TwoBody.jl b/src/TwoBody/TwoBody.jl index 034843b9..11d89999 100644 --- a/src/TwoBody/TwoBody.jl +++ b/src/TwoBody/TwoBody.jl @@ -38,7 +38,7 @@ export semimajor_axis, eccentricity, eccentricity_vector, inclination, true_ano time_since_periapsis, mean_motion, semi_parameter, conic_anomoly, specific_angular_momentum_vector, specific_angular_momentum, specific_energy, isapprox, isequal, TwobodyPropagationResult, kepler, conic, - orbital_elements, cartesian, isinvalid + keplerian, cartesian, isinvalid # Include all module source code include("twobody_states.jl") diff --git a/src/TwoBody/twobody_calculations.jl b/src/TwoBody/twobody_calculations.jl index 282ed537..15e0bae1 100644 --- a/src/TwoBody/twobody_calculations.jl +++ b/src/TwoBody/twobody_calculations.jl @@ -30,11 +30,11 @@ conic(orbit::Orbit) = conic(eccentricity(orbit)) """ Orbit(rᵢ, vᵢ, body) -Construct `Orbit` from Cartesian elements. +Construct `Orbit` from Cartesian elements (in the inertial frame). """ function Orbit(rᵢ, vᵢ, body) - e, a, i, Ω, ω, ν = orbital_elements(rᵢ, vᵢ, body) + e, a, i, Ω, ω, ν = keplerian(rᵢ, vᵢ, body) rₚ = perifocal(i,Ω,ν,rᵢ) vₚ = perifocal(i,Ω,ν,vᵢ) return Orbit{ @@ -90,12 +90,12 @@ function Orbit(e, a, i, Ω, ω, ν, body) end """ - orbital_elements(rᵢ, vᵢ, body::CelestialBody) + keplerian(rᵢ, vᵢ, body::CelestialBody) Returns a Keplarian representation of a Cartesian orbital state. Algorithm taught in ENAE601. """ -function orbital_elements(rᵢ, vᵢ, μ) +function keplerian(rᵢ, vᵢ, μ) î = SVector{3, Float64}([1, 0, 0]) ĵ = SVector{3, Float64}([0, 1, 0]) @@ -129,8 +129,8 @@ function orbital_elements(rᵢ, vᵢ, μ) uconvert(u"°", ν) end -orbital_elements(rᵢ, vᵢ, body::CelestialBody) = orbital_elements(rᵢ, vᵢ, body.μ) -orbital_elements(orbit::Orbit) = orbit.e, orbit.a, orbit.i, +keplerian(rᵢ, vᵢ, body::CelestialBody) = keplerian(rᵢ, vᵢ, body.μ) +keplerian(orbit::Orbit) = orbit.e, orbit.a, orbit.i, orbit.Ω, orbit.ω, orbit.ν """ From 58681cdbf628ca85cdbbca4fa1194686aed31de6 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 10:46:45 -0400 Subject: [PATCH 05/12] Updating toml files with new versions --- Manifest.toml | 70 ++++++++++++++++++++++++++++----------------------- Project.toml | 2 +- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 875b4821..1749e1e9 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,10 +1,10 @@ # This file is machine-generated - editing it directly is not advised [[AbstractAlgebra]] -deps = ["InteractiveUtils", "LinearAlgebra", "Markdown", "Random", "SparseArrays", "Test"] -git-tree-sha1 = "8fa03ecf25341ff3e8fb301dba3f41c6fe09952e" +deps = ["InteractiveUtils", "LinearAlgebra", "Markdown", "Random", "RandomExtensions", "SparseArrays", "Test"] +git-tree-sha1 = "b861cb913bc7e2e52e93bb9ad3def00bbd658889" uuid = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" -version = "0.10.0" +version = "0.11.0" [[Adapt]] deps = ["LinearAlgebra"] @@ -20,15 +20,15 @@ version = "0.0.4" [[ArrayInterface]] deps = ["LinearAlgebra", "Requires", "SparseArrays"] -git-tree-sha1 = "a7110d4291700c0d9ddbeb5fa41c3b9c4659c2aa" +git-tree-sha1 = "920136b6b8ae5bd28a3c45d68e55421dec156d7f" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "2.13.3" +version = "2.13.6" [[ArrayLayouts]] deps = ["Compat", "FillArrays", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "d6f1ecde467019346f7601fb2ee58cb2bc60d121" +git-tree-sha1 = "613ee839b41d4fb5aef6494a9ac998d058729051" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "0.4.8" +version = "0.4.9" [[Artifacts]] deps = ["Pkg"] @@ -37,10 +37,10 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" version = "1.3.0" [[BandedMatrices]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] -git-tree-sha1 = "9b90c8e22ff5a467ef14699bc38afac53885ac3e" +deps = ["ArrayLayouts", "Compat", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] +git-tree-sha1 = "c462231baa800ec25075747c97c6477fffa89873" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "0.15.21" +version = "0.15.24" [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -70,15 +70,15 @@ version = "0.5.1" [[CanonicalTraits]] deps = ["MLStyle"] -git-tree-sha1 = "e4581e3fadda3824e0df04396c85258a2107035d" +git-tree-sha1 = "fe3d23a57c0c9d9b99d7e65890a36c3de6b14906" uuid = "a603d957-0e48-4f86-8fbd-0b7bc66df689" -version = "0.2.2" +version = "0.2.3" [[ChainRulesCore]] deps = ["LinearAlgebra", "MuladdMacro"] -git-tree-sha1 = "bf716c385bbffdefc5503e8ae13ae6c2ceeb3038" +git-tree-sha1 = "a7e639087196dc62ce4f7cad7224735d7520e963" uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "0.9.13" +version = "0.9.16" [[ColorSchemes]] deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random", "StaticArrays"] @@ -111,9 +111,9 @@ version = "0.3.0" [[Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "cf03b37436c6bc162e7c8943001568b4cad4bee3" +git-tree-sha1 = "f76e41cf110de7176a657c72409e722cfc86fbb6" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.19.0" +version = "3.20.0" [[CompilerSupportLibraries_jll]] deps = ["Libdl", "Pkg"] @@ -171,9 +171,9 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[DelayDiffEq]] deps = ["DataStructures", "DiffEqBase", "LinearAlgebra", "Logging", "OrdinaryDiffEq", "Printf", "RecursiveArrayTools", "Reexport", "Roots", "UnPack"] -git-tree-sha1 = "a74a10a4c9885313b00e1f6409ef0fc8141af68e" +git-tree-sha1 = "406d5213a04d251ac751300d84f04ff34f5f8f11" uuid = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb" -version = "5.24.2" +version = "5.25.0" [[DelimitedFiles]] deps = ["Mmap"] @@ -292,9 +292,9 @@ version = "0.3.2" [[FillArrays]] deps = ["LinearAlgebra", "Random", "SparseArrays"] -git-tree-sha1 = "b955c227b0d1413a1a97e2ca0635a5de019d7337" +git-tree-sha1 = "502b3de6039d5b78c76118423858d981349f3823" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "0.9.6" +version = "0.9.7" [[FiniteDiff]] deps = ["ArrayInterface", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays"] @@ -415,9 +415,9 @@ uuid = "82899510-4779-5014-852e-03e436cf321d" version = "1.0.0" [[JLLWrappers]] -git-tree-sha1 = "dbc0967f6403829a6682493fdb4ec7c0ebfd2e68" +git-tree-sha1 = "7cec881362e5b4e367ff0279dd99a06526d51a55" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.1.1" +version = "1.1.2" [[JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -586,9 +586,9 @@ uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391" version = "0.1.5" [[OffsetArrays]] -git-tree-sha1 = "3fdfca8a532507d65f39ff0ad34fe81097a55337" +git-tree-sha1 = "a416e2f267e2c8729f25bcaf1ce19d2893faf393" uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.3.0" +version = "1.3.1" [[Ogg_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -679,9 +679,9 @@ version = "1.0.7" [[Plots]] deps = ["Base64", "Contour", "Dates", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "GeometryTypes", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"] -git-tree-sha1 = "9376c978098b85a001870ad0270569b6e445f154" +git-tree-sha1 = "f4425bbd5f313b074d6ce3b86d80c0ad16bf7326" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -version = "1.6.10" +version = "1.6.12" [[PoissonRandom]] deps = ["Random", "Statistics", "Test"] @@ -712,6 +712,12 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +[[RandomExtensions]] +deps = ["Random", "SparseArrays", "Test"] +git-tree-sha1 = "a1f5f900aaf39849bd59efcf751df79f1179bb73" +uuid = "fb686558-2515-59ef-acaa-46db3789a887" +version = "0.4.2" + [[RandomNumbers]] deps = ["Random", "Requires"] git-tree-sha1 = "441e6fc35597524ada7f85e13df1f4e10137d16f" @@ -731,9 +737,9 @@ version = "0.1.13" [[RecursiveArrayTools]] deps = ["ArrayInterface", "LinearAlgebra", "RecipesBase", "Requires", "StaticArrays", "Statistics", "ZygoteRules"] -git-tree-sha1 = "800236466c6932b9ddc78c1970706188fd8e14b4" +git-tree-sha1 = "639b3c4c7bcdc42be3ce69c4919eac17be73242b" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "2.7.1" +version = "2.7.2" [[RecursiveFactorization]] deps = ["LinearAlgebra", "LoopVectorization", "VectorizationBase"] @@ -749,9 +755,9 @@ version = "0.2.0" [[Requires]] deps = ["UUIDs"] -git-tree-sha1 = "2fc2e1ab606a5dca7bbad9036a694553c3a57926" +git-tree-sha1 = "28faf1c963ca1dc3ec87f166d92982e3c4a1f66d" uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.0.3" +version = "1.1.0" [[ResettableStacks]] deps = ["StaticArrays"] @@ -906,9 +912,9 @@ version = "5.2.0+1" [[SymbolicUtils]] deps = ["AbstractAlgebra", "Combinatorics", "DataStructures", "NaNMath", "SpecialFunctions", "TimerOutputs"] -git-tree-sha1 = "3cd0b83054bd456ac5c8740900ef4d1f830462c0" +git-tree-sha1 = "cd230ab5f02844155415aad28e8474fe459fe366" uuid = "d1185830-fcd6-423d-90d6-eec64667417b" -version = "0.5.1" +version = "0.5.2" [[TableTraits]] deps = ["IteratorInterfaceExtensions"] diff --git a/Project.toml b/Project.toml index 37b078a4..1a2f669c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "UnitfulAstrodynamics" uuid = "673e7d9c-15b0-48d3-bce0-fab551f3a174" authors = ["Joe Carpinelli "] -version = "0.5.0" +version = "0.6.0" [deps] ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" From 4605d87b2e40b8b1392a43cb6a2c82d568f6d570 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 11:05:47 -0400 Subject: [PATCH 06/12] Updating README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2c6cd9f2..f2d6e9c6 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ The `TwoBody` module handles Astrodynamics scenarios within the two-body problem ```Julia # Cartesian state to Orbit -r̅ = [0.0, 11681.0, 0.0]u"km" -v̅ = [5.134, 4.226, 2.787]u"km/s" -orbit1 = Orbit(r̅, v̅, Earth) +rᵢ = [0.0, 11681.0, 0.0] * u"km" +vᵢ = [5.134, 4.226, 2.787] * u"km/s" +orbit1 = Orbit(rᵢ, vᵢ, Earth) # Keplerian state to Orbit e = 0.3 * u"rad" @@ -65,16 +65,16 @@ The `NBody` module helps to solve the classical gravitational `NBody` problem. ```Julia # It's MY Earth, and I want it now -r̅₁ = [0.0, 0.0, 0.0]u"km" -v̅₁ = [0.0, 0.0, 0.0]u"km/s" +r₁ = [0.0, 0.0, 0.0]u"km" +v₁ = [0.0, 0.0, 0.0]u"km/s" m₁ = Earth.m -myEarth = Body(r̅₁, v̅₁, m₁) +myEarth = Body(r₁, v₁, m₁) # And we'll need a satellite... -r̅₂ = [0.0, 11681.0, 0.0]u"km" -v̅₂ = [5.134, 4.226, 2.787]u"km/s" +r₂ = [0.0, 11681.0, 0.0]u"km" +v₂ = [5.134, 4.226, 2.787]u"km/s" m₂ = 1000.0u"kg" -mySatellite = Body(r̅₂, v̅₂, m₂) +mySatellite = Body(r₂, v₂, m₂) # Construct a MultibodySystem sys = MultibodySystem([myEarth, mySatellite]) From 80755eee4de3eac1a5717efec0e4784088974c5d Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 11:39:46 -0400 Subject: [PATCH 07/12] Adding parent package to docs/Project.toml the right way! * Thanks [fredrikekre](https://discourse.julialang.org/t/documenter-jl-how-to-add-package/48496)! --- docs/Manifest.toml | 77 ++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/docs/Manifest.toml b/docs/Manifest.toml index 84eee2f8..55092691 100644 --- a/docs/Manifest.toml +++ b/docs/Manifest.toml @@ -1,10 +1,10 @@ # This file is machine-generated - editing it directly is not advised [[AbstractAlgebra]] -deps = ["InteractiveUtils", "LinearAlgebra", "Markdown", "Random", "SparseArrays", "Test"] -git-tree-sha1 = "8fa03ecf25341ff3e8fb301dba3f41c6fe09952e" +deps = ["InteractiveUtils", "LinearAlgebra", "Markdown", "Random", "RandomExtensions", "SparseArrays", "Test"] +git-tree-sha1 = "b861cb913bc7e2e52e93bb9ad3def00bbd658889" uuid = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" -version = "0.10.0" +version = "0.11.0" [[Adapt]] deps = ["LinearAlgebra"] @@ -20,15 +20,15 @@ version = "0.0.4" [[ArrayInterface]] deps = ["LinearAlgebra", "Requires", "SparseArrays"] -git-tree-sha1 = "40990a6dfd617d2f7d1375e9d4b52d962c8d6dcf" +git-tree-sha1 = "920136b6b8ae5bd28a3c45d68e55421dec156d7f" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "2.13.4" +version = "2.13.6" [[ArrayLayouts]] deps = ["Compat", "FillArrays", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "d6f1ecde467019346f7601fb2ee58cb2bc60d121" +git-tree-sha1 = "613ee839b41d4fb5aef6494a9ac998d058729051" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "0.4.8" +version = "0.4.9" [[Artifacts]] deps = ["Pkg"] @@ -37,10 +37,10 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" version = "1.3.0" [[BandedMatrices]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] -git-tree-sha1 = "9b90c8e22ff5a467ef14699bc38afac53885ac3e" +deps = ["ArrayLayouts", "Compat", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] +git-tree-sha1 = "c462231baa800ec25075747c97c6477fffa89873" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "0.15.21" +version = "0.15.24" [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -70,15 +70,15 @@ version = "0.5.1" [[CanonicalTraits]] deps = ["MLStyle"] -git-tree-sha1 = "e4581e3fadda3824e0df04396c85258a2107035d" +git-tree-sha1 = "fe3d23a57c0c9d9b99d7e65890a36c3de6b14906" uuid = "a603d957-0e48-4f86-8fbd-0b7bc66df689" -version = "0.2.2" +version = "0.2.3" [[ChainRulesCore]] -deps = ["LinearAlgebra", "MuladdMacro"] -git-tree-sha1 = "bf716c385bbffdefc5503e8ae13ae6c2ceeb3038" +deps = ["LinearAlgebra", "MuladdMacro", "SparseArrays"] +git-tree-sha1 = "aebbda0a7c644bd8739b34f2a1b1e48f114aab49" uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "0.9.13" +version = "0.9.17" [[ColorSchemes]] deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random", "StaticArrays"] @@ -144,6 +144,11 @@ git-tree-sha1 = "f0464e499ab9973b43c20f8216d088b61fda80c6" uuid = "adafc99b-e345-5852-983c-f28acb93d879" version = "0.2.2" +[[Crayons]] +git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.0.4" + [[DataAPI]] git-tree-sha1 = "176e23402d80e7743fc26c19c681bfb11246af32" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" @@ -166,9 +171,9 @@ uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" [[DelayDiffEq]] deps = ["DataStructures", "DiffEqBase", "LinearAlgebra", "Logging", "OrdinaryDiffEq", "Printf", "RecursiveArrayTools", "Reexport", "Roots", "UnPack"] -git-tree-sha1 = "a74a10a4c9885313b00e1f6409ef0fc8141af68e" +git-tree-sha1 = "406d5213a04d251ac751300d84f04ff34f5f8f11" uuid = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb" -version = "5.24.2" +version = "5.25.0" [[DelimitedFiles]] deps = ["Mmap"] @@ -282,9 +287,9 @@ version = "0.4.0" [[FFMPEG_jll]] deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] -git-tree-sha1 = "13a934b9e74a8722bf1786c989de346a9602e695" +git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f" uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" -version = "4.3.1+2" +version = "4.3.1+4" [[FastClosures]] git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" @@ -293,9 +298,9 @@ version = "0.3.2" [[FillArrays]] deps = ["LinearAlgebra", "Random", "SparseArrays"] -git-tree-sha1 = "b955c227b0d1413a1a97e2ca0635a5de019d7337" +git-tree-sha1 = "502b3de6039d5b78c76118423858d981349f3823" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "0.9.6" +version = "0.9.7" [[FiniteDiff]] deps = ["ArrayInterface", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays"] @@ -416,9 +421,9 @@ uuid = "82899510-4779-5014-852e-03e436cf321d" version = "1.0.0" [[JLLWrappers]] -git-tree-sha1 = "dbc0967f6403829a6682493fdb4ec7c0ebfd2e68" +git-tree-sha1 = "7cec881362e5b4e367ff0279dd99a06526d51a55" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.1.1" +version = "1.1.2" [[JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -680,9 +685,9 @@ version = "1.0.7" [[Plots]] deps = ["Base64", "Contour", "Dates", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "GeometryTypes", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"] -git-tree-sha1 = "9376c978098b85a001870ad0270569b6e445f154" +git-tree-sha1 = "f4425bbd5f313b074d6ce3b86d80c0ad16bf7326" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -version = "1.6.10" +version = "1.6.12" [[PoissonRandom]] deps = ["Random", "Statistics", "Test"] @@ -713,6 +718,12 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" deps = ["Serialization"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +[[RandomExtensions]] +deps = ["Random", "SparseArrays", "Test"] +git-tree-sha1 = "a1f5f900aaf39849bd59efcf751df79f1179bb73" +uuid = "fb686558-2515-59ef-acaa-46db3789a887" +version = "0.4.2" + [[RandomNumbers]] deps = ["Random", "Requires"] git-tree-sha1 = "441e6fc35597524ada7f85e13df1f4e10137d16f" @@ -732,9 +743,9 @@ version = "0.1.13" [[RecursiveArrayTools]] deps = ["ArrayInterface", "LinearAlgebra", "RecipesBase", "Requires", "StaticArrays", "Statistics", "ZygoteRules"] -git-tree-sha1 = "800236466c6932b9ddc78c1970706188fd8e14b4" +git-tree-sha1 = "639b3c4c7bcdc42be3ce69c4919eac17be73242b" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "2.7.1" +version = "2.7.2" [[RecursiveFactorization]] deps = ["LinearAlgebra", "LoopVectorization", "VectorizationBase"] @@ -907,9 +918,9 @@ version = "5.2.0+1" [[SymbolicUtils]] deps = ["AbstractAlgebra", "Combinatorics", "DataStructures", "NaNMath", "SpecialFunctions", "TimerOutputs"] -git-tree-sha1 = "3cd0b83054bd456ac5c8740900ef4d1f830462c0" +git-tree-sha1 = "cd230ab5f02844155415aad28e8474fe459fe366" uuid = "d1185830-fcd6-423d-90d6-eec64667417b" -version = "0.5.1" +version = "0.5.2" [[TableTraits]] deps = ["IteratorInterfaceExtensions"] @@ -970,12 +981,10 @@ uuid = "6112ee07-acf9-5e0f-b108-d242c714bf9f" version = "1.0.1" [[UnitfulAstrodynamics]] -deps = ["ComponentArrays", "DifferentialEquations", "LinearAlgebra", "Logging", "PhysicalConstants", "Plots", "Reexport", "Roots", "StaticArrays", "Unitful", "UnitfulAngles", "UnitfulAstro"] -git-tree-sha1 = "cf7f0c07b73db3efdb71d163f69b00d34a8dee33" -repo-rev = "main" -repo-url = "https://github.com/cadojo/UnitfulAstrodynamics.jl" +deps = ["ComponentArrays", "Crayons", "DifferentialEquations", "LinearAlgebra", "Logging", "PhysicalConstants", "Plots", "Reexport", "Roots", "StaticArrays", "Unitful", "UnitfulAngles", "UnitfulAstro"] +path = ".." uuid = "673e7d9c-15b0-48d3-bce0-fab551f3a174" -version = "0.5.0" +version = "0.6.0" [[VectorizationBase]] deps = ["CpuId", "Libdl", "LinearAlgebra"] From a13b7f006071bb30c408f675a034039770cf59ce Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 11:54:55 -0400 Subject: [PATCH 08/12] Updating docs and path --- README.md | 2 +- docs/src/index.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f2d6e9c6..2b993b41 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This package aims to provide a simple interface for common astrodynamics problem ## Usage -Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev/Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! +Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev/#Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! #### Two-body Problem diff --git a/docs/src/index.md b/docs/src/index.md index 023f9f52..ba5e5a34 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -24,9 +24,9 @@ The `TwoBody` module handles Astrodynamics scenarios within the two-body problem ```Julia # Cartesian state to Orbit -r̅ = [0.0, 11681.0, 0.0]u"km" -v̅ = [5.134, 4.226, 2.787]u"km/s" -orbit1 = Orbit(r̅, v̅, Earth) +r = [0.0, 11681.0, 0.0]u"km" +v = [5.134, 4.226, 2.787]u"km/s" +orbit1 = Orbit(r, v, Earth) # Keplerian state to Orbit e = 0.3 * u"rad" @@ -82,16 +82,16 @@ You can make your own `Body` by specifying an initial Cartesian state, and a mas ```Julia # It's MY Earth, and I want it now -r̅₁ = [0.0, 0.0, 0.0]u"km" -v̅₁ = [0.0, 0.0, 0.0]u"km/s" +r₁ = [0.0, 0.0, 0.0]u"km" +v₁ = [0.0, 0.0, 0.0]u"km/s" m₁ = Earth.m -myEarth = Body(r̅₁, v̅₁, m₁) +myEarth = Body(r₁, v₁, m₁) # And we'll need a satellite... -r̅₂ = [0.0, 11681.0, 0.0]u"km" -v̅₂ = [5.134, 4.226, 2.787]u"km/s" +r₂ = [0.0, 11681.0, 0.0]u"km" +v₂ = [5.134, 4.226, 2.787]u"km/s" m₂ = 1000.0u"kg" -mySatellite = Body(r̅₂, v̅₂, m₂) +mySatellite = Body(r₂, v₂, m₂) ``` A `MultibodySystem` contains an array of `Bodies`. From a1ec3abfb1fad2c8b91b4902a7112a882952c419 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 19:08:20 -0400 Subject: [PATCH 09/12] Adding custom printing for CelestialBody --- Project.toml | 2 +- src/TwoBody/twobody_states.jl | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 1a2f669c..db3df0fe 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "UnitfulAstrodynamics" uuid = "673e7d9c-15b0-48d3-bce0-fab551f3a174" authors = ["Joe Carpinelli "] -version = "0.6.0" +version = "0.5.1" [deps] ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" diff --git a/src/TwoBody/twobody_states.jl b/src/TwoBody/twobody_states.jl index b0bc0ab8..19a59584 100644 --- a/src/TwoBody/twobody_states.jl +++ b/src/TwoBody/twobody_states.jl @@ -72,6 +72,24 @@ struct CelestialBody CelestialBody(m, R) = new(m, R, G * m) end +""" + show(io::IO, body::CelestialBody) + +Custom display for `CelestialBody` instances. +""" +function Base.show(io::IO, body::CelestialBody) + + println(io, crayon"blue", "CelestialBody:") + println(io, crayon"cyan", + " Mass: ", ustrip(u"kg", body.m), " ", u"kg") + println(io, crayon"light_blue", + " Radius: ", ustrip(u"km", body.R), " ", u"km") + println(io, crayon"light_magenta", + " Mass Parameter: ", ustrip(u"km^3/s^2", body.μ), " ", u"km^3/s^2") + +end + + # All data pulled from the following references: # [1] https://en.wikipedia.org/wiki/List_of_Solar_System_objects_by_size @@ -154,7 +172,7 @@ end """ show(io::IO, orbit::Orbit) -Overloads Base.show() for ::Orbit instances. +Custom display for Orbit instances. """ function Base.show(io::IO, orbit::Orbit) @@ -223,4 +241,4 @@ InvalidOrbit(body::CelestialBody) = Orbit( Checks for `NaN` valued orbital states, which are used to indicate an invalid `Orbit`. """ -isinvalid(orbit::Orbit) = all(map(x->!isnan(getfield(orbit, x)), [:rᵢ, :vᵢ, :e, :a, :i, :Ω, :ω, :ν])) \ No newline at end of file +isinvalid(orbit::Orbit) = all(map(x->!isnan(getfield(orbit, x)), [:rᵢ, :vᵢ, :e, :a, :i, :Ω, :ω, :ν])) From a54aee12c9954366d8ca93dfd1ca6ef4301e3da0 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 19:12:51 -0400 Subject: [PATCH 10/12] Updating README.md with stable doc paths --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b993b41..406e838b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Tests](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Tests/badge.svg)](https://github.com/cadojo/UnitfulAstrodynamics.jl/actions?query=workflow%3ATests) -[![Docs](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Documentation/badge.svg)](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev) +[![Docs](https://github.com/cadojo/UnitfulAstrodynamics.jl/workflows/Documentation/badge.svg)](https://cadojo.github.io/UnitfulAstrodynamics.jl/stable) # UnitfulAstrodynamics.jl A simple Astrodynamics package, written with Julia! @@ -19,7 +19,7 @@ This package aims to provide a simple interface for common astrodynamics problem ## Usage -Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/dev/#Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! +Check out the [Getting Started](https://cadojo.github.io/UnitfulAstrodynamics.jl/stable/#Getting-Started) documentation for code examples, and more detail about using this package. Some quick examples are shown below! #### Two-body Problem From e545d372efad76fa424d94ec0fb97f073eef4d70 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 20:10:33 -0400 Subject: [PATCH 11/12] Update main.yml --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b7b290b..7497a9ff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,6 @@ jobs: matrix: version: - '1.5' - - 'nightly' os: - ubuntu-latest - macOS-latest From 35d4fe3b8f82a49404459f1b93830180b321b3a6 Mon Sep 17 00:00:00 2001 From: Joe Carpinelli Date: Fri, 16 Oct 2020 20:13:17 -0400 Subject: [PATCH 12/12] Create julia-latest.yml --- .github/workflows/julia-latest.yml | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/julia-latest.yml diff --git a/.github/workflows/julia-latest.yml b/.github/workflows/julia-latest.yml new file mode 100644 index 00000000..224e701c --- /dev/null +++ b/.github/workflows/julia-latest.yml @@ -0,0 +1,38 @@ + +name: Julia-Nightly +on: + schedule: + - cron: 0 0 * * * + workflow_dispatch: +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - 'nightly' + os: + - ubuntu-latest + - macOS-latest + arch: + - x64 + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-runtest@latest