# Coding Standards - Orbital Mechanics Simulation ## Code Style - **C-style C++**: structs and functions only, NO classes or templates - **File extensions**: Use `.cpp` extensions for all source files (for future C++ features if needed) - **Include guards**: All headers use include guards (e.g., `#ifndef MODULE_NAME_H`) - **Function design**: Small, focused functions with single responsibilities ```cpp // Header file with include guard #ifndef ORBITAL_MECHANICS_H #define ORBITAL_MECHANICS_H struct OrbitalElements { double semi_major_axis; double eccentricity; double true_anomaly; }; OrbitalElements propagate_orbital_elements(OrbitalElements elements, double dt, double parent_mass); #endif ``` ## Naming Conventions **Struct names**: PascalCase ```cpp struct CelestialBody { }; struct OrbitalElements { }; struct Spacecraft { }; ``` **Function names**: snake_case ```cpp propagate_orbital_elements() find_dominant_body() update_bodies_physics() ``` **Member variables**: snake_case ```cpp global_position local_velocity parent_index ``` **Constants**: UPPER_CASE ```cpp PARABOLIC_TOLERANCE MIN_MASS_RATIO ``` **Enum values**: UPPER_CASE with prefix ```cpp enum BurnDirection { BURN_PROGRADE, BURN_RETROGRADE }; enum TriggerType { TRIGGER_TIME, TRIGGER_TRUE_ANOMALY }; ``` ## Comments - **Minimal comments**: Code should be self-documenting - **Non-obvious logic only**: Comment only what cannot be inferred from the code - **No decorative blocks**: No `===`, `---`, or ASCII art comment blocks ```cpp // Good: minimal comments if (vec3_distance(pos, parent_pos) > soi_radius) { return 0; } // Bad: excessive decoration // ======================================== // SOI Check Function // ======================================== // This function checks if we're in SOI // ======================================== ``` ## Whitespace - **No trailing whitespace**: All files (including markdown) must not have trailing whitespace - **Pre-commit hook**: Automatically strips trailing whitespace - **Markdown line breaks**: Use `
` tag instead of two trailing spaces ```markdown Good: Line 1
Line 2 Bad: Line 2 Line 4 ``` ## Memory Management - **Dynamic arrays**: Use `malloc` and `free` - **Struct-based design**: No RAII or smart pointers - **Manual cleanup**: Destroy functions handle cleanup ```cpp // Allocation SimulationState* sim = malloc(sizeof(SimulationState)); sim->bodies = malloc(max_bodies * sizeof(CelestialBody)); // Cleanup void destroy_simulation(SimulationState* sim) { free(sim->bodies); free(sim->spacecraft); free(sim); } ``` ## Code Organization **Layer separation**: Physics, Simulation, Configuration, Rendering layers **Physics module independence**: Physics functions use parameter-based signatures, no dependencies on simulation structures ```cpp // Good: parameter-based, independent Vec3 vec3_add(Vec3 a, Vec3 b); Mat3 mat3_rotation_orbital(double omega, double i, double omega_upper); // Avoid: depends on specific structures Vec3 compute_global_position(CelestialBody* body); // Simulation layer ``` **Headers vs implementation**: - Headers (`.h`): Declarations only - Implementation (`.cpp`): Function definitions ## Floating-Point Comparisons (Testing) - **Use `WithinAbs()`**: Required for floating-point comparisons - **Avoid `Approx()`**: Deprecated in Catch2 - **Required header**: `` ```cpp #include TEST_CASE("orbital energy conservation") { double energy = calculate_total_energy(sim); REQUIRE_THAT(energy, WithinAbs(expected, 1e-6)); } ``` ## Git Workflow - **Small commits**: Logical separation of changes - **Concise messages**: One-line commit messages preferred - **Build before commit**: Run `make && make test` before committing ```bash # Verify build and tests pass make && make test # Commit with descriptive message git add . git commit -m "add parabolic orbit propagation" ``` ## Build System **Makefile targets**: - `make` or `make all`: Build simulation - `make test`: Build and run automated tests - `make clean`: Remove build artifacts - `make rebuild`: Clean and rebuild **Default configuration**: - Time step: 60 seconds for solar system scale - Physics steps per frame: 100 (default) - Simulation time per frame: 60s × 100 = 6000 seconds at 1× speed ```bash # Full build make # Run tests make test # Clean and rebuild make rebuild ``` ## Physics Considerations **Time step**: 60 seconds for solar system scale **Circular orbit velocity**: ```cpp v = sqrt(G * M / r) ``` **Sphere of Influence (SOI)**: Hill sphere approximation ```cpp r_soi = a * (m / M)^(2/5) ``` **SOI transitions**: 0.5× distance hysteresis to prevent oscillation **Parabolic orbits**: Escape velocity ```cpp v² = 2GM / r ``` **Hyperbolic orbits**: Positive total energy with asymptotic velocity at infinity **Analytical propagation**: Uses Kepler equation solvers (not RK4 integration) - Elliptical: E - e·sin(E) = M - Parabolic: D + D³/3 = M (Barker's equation) - Hyperbolic: H - e·sinh(H) = M ## Module Dependencies ``` Physics (foundation, no dependencies) ↓ Orbital Mechanics (depends only on Physics) ↓ Spacecraft, Maneuver (depend on Physics) ↓ Simulation (depends on Physics, Orbital Mechanics, Spacecraft, Maneuver) ↓ Config Loader (depends on Simulation) Config Validator (depends on Simulation and Orbital Mechanics) Renderer (depends on Simulation) UI Renderer (depends on Renderer and Simulation) ``` **Key principles**: - Physics is completely independent - Lower layers never depend on upper layers - Each module has clear, minimal dependencies ## Testing Guidelines - **Framework**: Catch2 - **Run tests**: `make test` - **Test configs**: Located in `tests/configs/` - **Descriptive names**: Use clear test case names ```bash # Run all tests make test # Run specific test config ./orbit_test '[config_name]' # Test with debug output (shows INFO messages) ./orbit_test -s '[config_name]' ``` **Test structure**: ```cpp TEST_CASE("elliptical orbit energy conservation", "[energy]") { SimulationState* sim = create_simulation(10, 1, 0, 60.0); load_system_config(sim, "tests/configs/elliptical.toml"); double initial_energy = calculate_system_total_energy(sim); for (int i = 0; i < 100; i++) { update_simulation(sim); } double final_energy = calculate_system_total_energy(sim); REQUIRE_THAT(final_energy, WithinAbs(initial_energy, 1e-6)); destroy_simulation(sim); } ``` ## Common Patterns **Struct initialization**: ```cpp CelestialBody earth = {0}; strcpy(earth.name, "Earth"); earth.mass = 5.972e24; earth.radius = 6.371e6; ``` **Error handling**: Return codes or NULL pointers ```cpp int result = some_function(); if (result != 0) { return result; } CelestialBody* body = find_body(sim, "Earth"); if (body == NULL) { return -1; } ``` **Const correctness**: Use `const` for read-only parameters ```cpp Vec3 vec3_add(const Vec3 a, const Vec3 b) { Vec3 result = { a.x + b.x, a.y + b.y, a.z + b.z }; return result; } ``` ## File Organization **Directory structure**: ``` src/ physics.h/cpp orbital_mechanics.h/cpp simulation.h/cpp spacecraft.h/cpp maneuver.h/cpp config_loader.h/cpp config_validator.h/cpp renderer.h/cpp ui_renderer.h/cpp test_utilities.h/cpp tests/ test_*.cpp configs/ configs/ *.toml docs/ *.md ``` ## Pre-commit Hooks The project uses a pre-commit hook that: - Strips trailing whitespace from all files - Prevents commits with trailing whitespace **If you see a "trailing whitespace" error**: 1. The hook has automatically fixed the files 2. Review the changes 3. Stage them again and retry the commit