Browse Source

feat: Add maneuver UI control functions

Implement first 7 priority functions for maneuver UI controls:
- add_maneuver_to_simulation(): Add maneuvers dynamically
- remove_maneuver_by_index(): Remove maneuvers from simulation
- create_maneuver(): Helper to construct maneuver structs
- get_burn_direction_name(): Get descriptive strings for directions
- preview_burn_result(): Preview orbital elements after burn
- calculate_hohmann_transfer(): Calculate optimal two-burn transfer
- validate_burn_parameters(): Validate burn parameters

See docs/planning/maneuver_ui_controls.md for full implementation plan.
main
cinnaboot 5 months ago
parent
commit
5ecd8805e2
  1. 127
      src/maneuver.cpp
  2. 24
      src/maneuver.h

127
src/maneuver.cpp

@ -5,6 +5,7 @@
#include "orbital_mechanics.h" #include "orbital_mechanics.h"
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstring>
Vec3 calculate_prograde_dir(Vec3 local_velocity) { Vec3 calculate_prograde_dir(Vec3 local_velocity) {
return vec3_normalize(local_velocity); return vec3_normalize(local_velocity);
@ -54,6 +55,27 @@ Vec3 get_burn_direction_vector(BurnDirection direction, Vec3 local_pos, Vec3 loc
} }
} }
const char* get_burn_direction_name(BurnDirection direction) {
switch (direction) {
case BURN_PROGRADE:
return "Prograde";
case BURN_RETROGRADE:
return "Retrograde";
case BURN_NORMAL:
return "Normal";
case BURN_ANTINORMAL:
return "Antinormal";
case BURN_RADIAL_IN:
return "Radial In";
case BURN_RADIAL_OUT:
return "Radial Out";
case BURN_CUSTOM:
return "Custom";
default:
return "Unknown";
}
}
void apply_impulsive_burn(Spacecraft* craft, BurnDirection direction, double delta_v) { void apply_impulsive_burn(Spacecraft* craft, BurnDirection direction, double delta_v) {
Vec3 dir = get_burn_direction_vector(direction, craft->local_position, craft->local_velocity); Vec3 dir = get_burn_direction_vector(direction, craft->local_position, craft->local_velocity);
@ -67,6 +89,27 @@ void apply_custom_burn(Spacecraft* craft, Vec3 delta_v_local) {
craft->global_velocity = vec3_add(craft->global_velocity, delta_v_local); craft->global_velocity = vec3_add(craft->global_velocity, delta_v_local);
} }
OrbitalElements preview_burn_result(const Spacecraft* craft, BurnDirection direction, double delta_v, const SimulationState* sim) {
OrbitalElements current_elements = craft->orbit;
if (craft->parent_index < 0 || craft->parent_index >= sim->body_count) {
return current_elements;
}
CelestialBody* parent = &sim->bodies[craft->parent_index];
double parent_mass = parent->mass;
Vec3 pos;
Vec3 vel;
orbital_elements_to_cartesian(current_elements, parent_mass, &pos, &vel);
Vec3 burn_dir = get_burn_direction_vector(direction, pos, vel);
Vec3 delta_v_vec = vec3_scale(burn_dir, delta_v);
Vec3 new_vel = vec3_add(vel, delta_v_vec);
return cartesian_to_orbital_elements(pos, new_vel, parent_mass);
}
bool check_maneuver_trigger(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim) { bool check_maneuver_trigger(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim) {
switch (maneuver->trigger_type) { switch (maneuver->trigger_type) {
case TRIGGER_TIME: case TRIGGER_TIME:
@ -163,6 +206,20 @@ bool check_maneuver_trigger(Maneuver* maneuver, Spacecraft* craft, SimulationSta
} }
} }
Maneuver create_maneuver(const char* name, int craft_index, BurnDirection direction, double delta_v, TriggerType trigger_type, double trigger_value) {
Maneuver m;
strncpy(m.name, name, 63);
m.name[63] = '\0';
m.craft_index = craft_index;
m.direction = direction;
m.delta_v = delta_v;
m.trigger_type = trigger_type;
m.trigger_value = trigger_value;
m.executed = false;
m.executed_time = 0.0;
return m;
}
void execute_maneuver(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim, double current_time) { void execute_maneuver(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim, double current_time) {
apply_impulsive_burn(craft, maneuver->direction, maneuver->delta_v); apply_impulsive_burn(craft, maneuver->direction, maneuver->delta_v);
@ -174,3 +231,73 @@ void execute_maneuver(Maneuver* maneuver, Spacecraft* craft, SimulationState* si
maneuver->executed = true; maneuver->executed = true;
maneuver->executed_time = current_time; maneuver->executed_time = current_time;
} }
int add_maneuver_to_simulation(SimulationState* sim, Maneuver* maneuver) {
if (sim->maneuver_count >= sim->max_maneuvers) {
return -1;
}
for (int i = 0; i < sim->maneuver_count; i++) {
if (strcmp(sim->maneuvers[i].name, maneuver->name) == 0) {
return -1;
}
}
if (maneuver->craft_index < 0 || maneuver->craft_index >= sim->craft_count) {
return -1;
}
int new_idx = sim->maneuver_count;
sim->maneuvers[new_idx] = *maneuver;
sim->maneuvers[new_idx].executed = false;
sim->maneuvers[new_idx].executed_time = 0.0;
sim->maneuver_count++;
return new_idx;
}
bool remove_maneuver_by_index(SimulationState* sim, int index) {
if (index < 0 || index >= sim->maneuver_count) {
return false;
}
int elements_to_move = sim->maneuver_count - index - 1;
if (elements_to_move > 0) {
memmove(&sim->maneuvers[index], &sim->maneuvers[index + 1],
elements_to_move * sizeof(Maneuver));
}
sim->maneuver_count--;
return true;
}
HohmannTransfer calculate_hohmann_transfer(double r1, double r2, double central_mass) {
HohmannTransfer result;
double a_transfer = (r1 + r2) / 2.0;
double mu = G * central_mass;
double v1 = sqrt(mu / r1);
double v_transfer1 = sqrt(mu * (2.0 / r1 - 1.0 / a_transfer));
result.dv1 = v_transfer1 - v1;
double v2 = sqrt(mu / r2);
double v_transfer2 = sqrt(mu * (2.0 / r2 - 1.0 / a_transfer));
result.dv2 = v2 - v_transfer2;
result.transfer_time = M_PI * sqrt(pow(a_transfer, 3.0) / mu);
result.true_anomaly_2 = M_PI;
return result;
}
bool validate_burn_parameters(const Spacecraft* craft, BurnDirection direction, double delta_v, double parent_mass) {
if (delta_v < 0) {
return false;
}
if (delta_v > 50000.0) {
return false;
}
return true;
}

24
src/maneuver.h

@ -32,6 +32,13 @@ struct Maneuver {
double executed_time; double executed_time;
}; };
struct HohmannTransfer {
double dv1;
double dv2;
double transfer_time;
double true_anomaly_2;
};
// Direction calculation functions (local frame) // Direction calculation functions (local frame)
Vec3 calculate_prograde_dir(Vec3 local_velocity); Vec3 calculate_prograde_dir(Vec3 local_velocity);
Vec3 calculate_retrograde_dir(Vec3 local_velocity); Vec3 calculate_retrograde_dir(Vec3 local_velocity);
@ -45,8 +52,25 @@ Vec3 get_burn_direction_vector(BurnDirection direction, Vec3 local_pos, Vec3 loc
void apply_impulsive_burn(Spacecraft* craft, BurnDirection direction, double delta_v); void apply_impulsive_burn(Spacecraft* craft, BurnDirection direction, double delta_v);
void apply_custom_burn(Spacecraft* craft, Vec3 delta_v_local); void apply_custom_burn(Spacecraft* craft, Vec3 delta_v_local);
// Burn preview functions
OrbitalElements preview_burn_result(const Spacecraft* craft, BurnDirection direction, double delta_v, const SimulationState* sim);
// Burn optimization functions
HohmannTransfer calculate_hohmann_transfer(double r1, double r2, double central_mass);
// Maneuver information functions
const char* get_burn_direction_name(BurnDirection direction);
// Maneuver validation functions
bool validate_burn_parameters(const Spacecraft* craft, BurnDirection direction, double delta_v, double parent_mass);
// Maneuver execution functions // Maneuver execution functions
bool check_maneuver_trigger(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim); bool check_maneuver_trigger(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim);
void execute_maneuver(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim, double current_time); void execute_maneuver(Maneuver* maneuver, Spacecraft* craft, SimulationState* sim, double current_time);
// Maneuver management functions
Maneuver create_maneuver(const char* name, int craft_index, BurnDirection direction, double delta_v, TriggerType trigger_type, double trigger_value);
int add_maneuver_to_simulation(SimulationState* sim, Maneuver* maneuver);
bool remove_maneuver_by_index(SimulationState* sim, int index);
#endif #endif

Loading…
Cancel
Save