Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor & fix inclination == 0 edge case #1

Merged
merged 1 commit into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 124 additions & 45 deletions examples/orbit_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bevy::pbr::NotShadowCaster;
use bevy::prelude::*;
use bevy_egui::egui::{ComboBox, DragValue, Ui};
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use keplerian_elements::astro::standard_gravitational_parameter;
use keplerian_elements::constants::AU;
use keplerian_elements::utils::{yup2zup, zup2yup};
use keplerian_elements::{KeplerianElements, StateVectors};
Expand Down Expand Up @@ -99,7 +100,11 @@ fn ui(
f32::MIN,
f32::MAX,
);
value_slider(ui, "Eccentricity", &mut orbit.eccentricity);
value_slider(
ui,
"Eccentricity",
&mut orbit.eccentricity,
);
value_slider(ui, "Inclination", &mut orbit.inclination);
value_slider(
ui,
Expand All @@ -111,7 +116,11 @@ fn ui(
"Argument of periapsis",
&mut orbit.argument_of_periapsis,
);
value_slider(ui, "Mean anomaly", &mut orbit.mean_anomaly_at_epoch);
value_slider(
ui,
"Mean anomaly",
&mut orbit.mean_anomaly_at_epoch,
);
value_slider(ui, "Epoch", &mut orbit.epoch);

let v = orbit.true_anomaly_at_epoch(
Expand All @@ -123,9 +132,12 @@ fn ui(
ui.label(format!("True anomaly: {v}",));

let e = orbit.eccentricity;
let h = orbit.specific_angular_momentum(state.star_mass);
let h =
orbit.specific_angular_momentum(state.star_mass);
let μ =
KeplerianElements::standard_gravitational_parameter(state.star_mass);
standard_gravitational_parameter(
state.star_mass,
);

let r = (h.powi(2) / μ) / (1.0 + e * v.cos());
ui.label(format!("r: {r}"));
Expand All @@ -139,19 +151,21 @@ fn ui(
ui.label(format!("vp: {vp}",));
ui.label(format!("vq: {vq}",));

planet.state_vectors = planet.orbit.state_vectors_at_epoch(
state.star_mass,
state.epoch,
state.tolerance,
);
planet.state_vectors =
planet.orbit.state_vectors_at_epoch(
state.star_mass,
state.epoch,
state.tolerance,
);
});

// --- State Vectors ---
ui.collapsing("State Vectors", |ui| {
let sv = &mut planet.state_vectors;
ui.label("Position");

let mut p = zup2yup(sv.position * state.distance_scaling);
let mut p =
zup2yup(sv.position * state.distance_scaling);

value_slider(ui, "X", &mut p.x);
value_slider(ui, "Y", &mut p.y);
Expand All @@ -161,24 +175,36 @@ fn ui(

ui.label("Velocity");

let mut v =
zup2yup(sv.velocity * state.distance_scaling * state.velocity_scaling);
let mut v = zup2yup(
sv.velocity
* state.distance_scaling
* state.velocity_scaling,
);

value_slider(ui, "Vx", &mut v.x);
value_slider(ui, "Vy", &mut v.y);
value_slider(ui, "Vz", &mut v.z);

sv.velocity =
yup2zup(v / (state.distance_scaling * state.velocity_scaling));
sv.velocity = yup2zup(
v / (state.distance_scaling
* state.velocity_scaling),
);

planet.orbit = sv.to_elements(state.star_mass, state.epoch);
planet.orbit =
sv.to_elements(state.star_mass, state.epoch);
});
});
}
});

ui.collapsing("State", |ui| {
value_slider_min_max(ui, "Tolerance", &mut state.tolerance, f32::EPSILON, 100.0);
value_slider_min_max(
ui,
"Tolerance",
&mut state.tolerance,
f32::EPSILON,
100.0,
);
value_slider(ui, "Mass", &mut state.star_mass);
value_slider(ui, "Epoch", &mut state.epoch);
value_slider(ui, "Epoch scale", &mut state.epoch_scale);
Expand All @@ -197,7 +223,11 @@ fn ui(
"Show position & velocity",
);

value_slider_u32(ui, "Orbit subdivisions", &mut state.orbit_subdivisions);
value_slider_u32(
ui,
"Orbit subdivisions",
&mut state.orbit_subdivisions,
);
}

ui.checkbox(&mut state.draw_soi, "Draw SOI");
Expand All @@ -224,17 +254,33 @@ fn ui(
ui.label("Mouse rotate sensitivity");
ui.horizontal(|ui| {
ui.label("x");
ui.add(DragValue::new(&mut camera.mouse_rotate_sensitivity.x).speed(0.01));
ui.add(
DragValue::new(&mut camera.mouse_rotate_sensitivity.x)
.speed(0.01),
);
ui.label("y");
ui.add(DragValue::new(&mut camera.mouse_rotate_sensitivity.y).speed(0.01));
ui.add(
DragValue::new(&mut camera.mouse_rotate_sensitivity.y)
.speed(0.01),
);
});

ui.label("Mouse translate sensitivity");
ui.horizontal(|ui| {
ui.label("x");
ui.add(DragValue::new(&mut camera.mouse_translate_sensitivity.x).speed(0.01));
ui.add(
DragValue::new(
&mut camera.mouse_translate_sensitivity.x,
)
.speed(0.01),
);
ui.label("y");
ui.add(DragValue::new(&mut camera.mouse_translate_sensitivity.y).speed(0.01));
ui.add(
DragValue::new(
&mut camera.mouse_translate_sensitivity.y,
)
.speed(0.01),
);
});
});
}
Expand Down Expand Up @@ -273,7 +319,10 @@ fn ui(

for (_, name) in &planets {
if ui
.selectable_label(current == name.to_string(), &name.to_string())
.selectable_label(
current == name.to_string(),
&name.to_string(),
)
.clicked()
{
state.focus_mode = FocusMode::Planet(name.to_string());
Expand All @@ -287,7 +336,13 @@ fn value_slider(ui: &mut Ui, name: &str, value: &mut f32) {
value_slider_min_max(ui, name, value, f32::MIN, f32::MAX)
}

fn value_slider_min_max(ui: &mut Ui, name: &str, value: &mut f32, min: f32, max: f32) {
fn value_slider_min_max(
ui: &mut Ui,
name: &str,
value: &mut f32,
min: f32,
max: f32,
) {
value_slider_min_max_with_speed(ui, name, value, min, max, 0.01);
}

Expand Down Expand Up @@ -531,7 +586,8 @@ fn spawn_solar_system(
eccentricity: 0.09339410,
semi_major_axis: 1.52371034 * AU,
inclination: 0.03232349774693498376462675303241,
right_ascension_of_the_ascending_node: 0.86760317116638123268876668101569,
right_ascension_of_the_ascending_node:
0.86760317116638123268876668101569,
argument_of_periapsis: 5.8657025501025428421251399347365,
mean_anomaly_at_epoch: 6.2034237603634456152598740984391,
epoch: 0.0,
Expand All @@ -552,7 +608,8 @@ fn spawn_solar_system(
eccentricity: 0.04854,
semi_major_axis: 5.2025 * AU,
inclination: 0.02267182698340634120423874308267,
right_ascension_of_the_ascending_node: 1.7503907068251131326967694717172,
right_ascension_of_the_ascending_node:
1.7503907068251131326967694717172,
argument_of_periapsis: 0.24905848425959083062701067266333,
mean_anomaly_at_epoch: 0.59917153220965334375790304082214,
epoch: 0.0,
Expand All @@ -573,7 +630,8 @@ fn spawn_solar_system(
eccentricity: 0.05551,
semi_major_axis: 9.5415 * AU,
inclination: 0.04352851154473857964847684776611,
right_ascension_of_the_ascending_node: 1.9833921619663561312160821893105,
right_ascension_of_the_ascending_node:
1.9833921619663561312160821893105,
argument_of_periapsis: 1.6207127434019344451313392476185,
mean_anomaly_at_epoch: 0.8740608893987602521233843368591,
epoch: 0.0,
Expand All @@ -594,7 +652,8 @@ fn spawn_solar_system(
eccentricity: 0.04686,
semi_major_axis: 19.188 * AU,
inclination: 0.01349139511791616762962012964042,
right_ascension_of_the_ascending_node: 1.2908455147750061550927616923742,
right_ascension_of_the_ascending_node:
1.2908455147750061550927616923742,
argument_of_periapsis: 3.0094712292138224894895199921049,
mean_anomaly_at_epoch: 5.4838245097661835306942363945912,
epoch: 0.0,
Expand All @@ -615,7 +674,8 @@ fn spawn_solar_system(
eccentricity: 0.00895,
semi_major_axis: 30.070 * AU,
inclination: 0.03089232776029963351154932660225,
right_ascension_of_the_ascending_node: 2.3001694212033269494277320637911,
right_ascension_of_the_ascending_node:
2.3001694212033269494277320637911,
argument_of_periapsis: 0.81471969483095304650797885073048,
mean_anomaly_at_epoch: 5.3096406504171494389172520558961,
epoch: 0.0,
Expand All @@ -632,12 +692,16 @@ fn update_epoch(time: Res<Time>, mut state: ResMut<State>) {
}
}

fn update_planets(mut query: Query<(&mut Transform, &mut Planet)>, state: Res<State>) {
fn update_planets(
mut query: Query<(&mut Transform, &mut Planet)>,
state: Res<State>,
) {
for (mut transform, mut planet) in query.iter_mut() {
planet.state_vectors =
planet
.orbit
.state_vectors_at_epoch(state.star_mass, state.epoch, state.tolerance);
planet.state_vectors = planet.orbit.state_vectors_at_epoch(
state.star_mass,
state.epoch,
state.tolerance,
);

let position = zup2yup(planet.state_vectors.position);

Expand All @@ -646,9 +710,13 @@ fn update_planets(mut query: Query<(&mut Transform, &mut Planet)>, state: Res<St
}
}

fn update_star(mut query: Query<&mut Transform, With<Star>>, state: Res<State>) {
fn update_star(
mut query: Query<&mut Transform, With<Star>>,
state: Res<State>,
) {
for mut transform in query.iter_mut() {
transform.scale = Vec3::ONE * mass2radius(state.as_ref(), state.star_mass);
transform.scale =
Vec3::ONE * mass2radius(state.as_ref(), state.star_mass);
}
}

Expand Down Expand Up @@ -692,7 +760,8 @@ fn draw_orbits(
let color = materials.get(mat).unwrap().base_color;

let first_position =
zup2yup(orbit.position_at_true_anomaly(state.star_mass, 0.0)) * state.distance_scaling;
zup2yup(orbit.position_at_true_anomaly(state.star_mass, 0.0))
* state.distance_scaling;
let mut prev_position = first_position.clone();

let step = (2.0 * PI) / state.orbit_subdivisions as f32;
Expand All @@ -714,8 +783,12 @@ fn draw_orbits(
let mut debug_arrows = DebugArrows::new(&mut lines, camera_position);

if state.show_position_and_velocity {
let StateVectors { position, velocity } =
orbit.state_vectors_at_epoch(state.star_mass, state.epoch, state.tolerance);
let StateVectors { position, velocity } = orbit
.state_vectors_at_epoch(
state.star_mass,
state.epoch,
state.tolerance,
);

let position = zup2yup(position);
let velocity = zup2yup(velocity);
Expand All @@ -730,25 +803,29 @@ fn draw_orbits(
if state.show_nodes {
debug_arrows.draw_arrow(
Vec3::ZERO,
zup2yup(orbit.ascending_node(state.star_mass)) * state.distance_scaling,
zup2yup(orbit.ascending_node(state.star_mass))
* state.distance_scaling,
Color::YELLOW_GREEN,
);
debug_arrows.draw_arrow(
Vec3::ZERO,
zup2yup(orbit.descending_node(state.star_mass)) * state.distance_scaling,
zup2yup(orbit.descending_node(state.star_mass))
* state.distance_scaling,
Color::YELLOW,
);
}

if state.show_peri_and_apo_apsis {
debug_arrows.draw_arrow(
Vec3::ZERO,
zup2yup(orbit.periapsis(state.star_mass)) * state.distance_scaling,
zup2yup(orbit.periapsis(state.star_mass))
* state.distance_scaling,
Color::WHITE,
);
debug_arrows.draw_arrow(
Vec3::ZERO,
zup2yup(orbit.apoapsis(state.star_mass)) * state.distance_scaling,
zup2yup(orbit.apoapsis(state.star_mass))
* state.distance_scaling,
Color::WHITE,
);
}
Expand All @@ -772,10 +849,12 @@ fn draw_soi(
for planet in planets.iter() {
let r = planet.state_vectors.position.length();

let soi = keplerian_elements::astro::soi(r, planet.mass, state.star_mass)
* state.distance_scaling;
let soi =
keplerian_elements::astro::soi(r, planet.mass, state.star_mass)
* state.distance_scaling;

let pos = zup2yup(planet.state_vectors.position) * state.distance_scaling;
let pos =
zup2yup(planet.state_vectors.position) * state.distance_scaling;

let to_camera = (camera_position - pos).normalize();
let planet_camera_radial = to_camera.cross(pos).normalize();
Expand Down
3 changes: 3 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
max_width = 80
imports_granularity = "Module"
group_imports = "StdExternalCrate"
11 changes: 8 additions & 3 deletions src/astro.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use crate::constants::G;
use crate::Num;

pub fn soi(r: Num, m1: Num, m2: Num) -> Num {
r * (m1 / m2).powf(2.0 / 5.0)
}
pub mod elliptic;
pub mod hyperbolic;

/// https://en.wikipedia.org/wiki/Standard_gravitational_parameter
#[inline]
pub fn standard_gravitational_parameter(mass: Num) -> Num {
G * mass
}

pub fn soi(r: Num, m1: Num, m2: Num) -> Num {
r * (m1 / m2).powf(2.0 / 5.0)
}
Loading