Browse Source

tests: improve rendezvous_hohmann integration test

Reduce TIME_STEP from 10.0 to 0.1 and increase MAX_STEPS to 700000
to achieve sub-10m rendezvous accuracy. Update milestone dump timing
to correctly capture pre/post-burn states. Revert test config to
original values to match test expectations.
main
cinnaboot 3 months ago
parent
commit
faf59e03a5
  1. 427
      tests/test_rendezvous_hohmann.cpp

427
tests/test_rendezvous_hohmann.cpp

@ -6,6 +6,7 @@
#include "../src/orbital_objects.h"
#include "../src/rendezvous_hohmann.h"
#include "../src/config_loader.h"
#include "../src/test_utilities.h"
#include <cmath>
#include <cstring>
@ -17,8 +18,6 @@ using Catch::Matchers::WithinAbs;
// Helper Functions
// ============================================================================
// TODO: Add find_spacecraft_by_name() to simulation.h interface
// FIXME: This helper should be part of the public simulation API for testability
static int find_spacecraft_by_name(SimulationState* sim, const char* name) {
for (int i = 0; i < sim->craft_count; i++) {
if (strcmp(sim->spacecraft[i].name, name) == 0) {
@ -48,21 +47,13 @@ TEST_CASE("Config loading for Hohmann transfer", "[rendezvous_hohmann][config]")
REQUIRE(sim->spacecraft[1].parent_index == 0);
REQUIRE(sim->spacecraft[2].parent_index == 0);
// Verify initial orbits
REQUIRE_THAT(sim->spacecraft[0].orbit.semi_major_axis,
WithinAbs(6.771e6, 1.0)); // 400 km altitude
REQUIRE_THAT(sim->spacecraft[1].orbit.semi_major_axis,
WithinAbs(6.671e6, 1.0)); // 300 km altitude
REQUIRE_THAT(sim->spacecraft[2].orbit.semi_major_axis,
WithinAbs(6.871e6, 1.0)); // 500 km altitude
// Verify initial true anomalies
REQUIRE_THAT(sim->spacecraft[0].orbit.true_anomaly,
WithinAbs(0.0, 0.001));
REQUIRE_THAT(sim->spacecraft[1].orbit.true_anomaly,
WithinAbs(4.71238898038469, 0.001)); // 270° = 3π/2
REQUIRE_THAT(sim->spacecraft[2].orbit.true_anomaly,
WithinAbs(1.5707963267948966, 0.001)); // 90° = π/2
REQUIRE_THAT(sim->spacecraft[0].orbit.semi_major_axis, WithinAbs(6.771e6, 1.0));
REQUIRE_THAT(sim->spacecraft[1].orbit.semi_major_axis, WithinAbs(6.671e6, 1.0));
REQUIRE_THAT(sim->spacecraft[2].orbit.semi_major_axis, WithinAbs(6.871e6, 1.0));
REQUIRE_THAT(sim->spacecraft[0].orbit.true_anomaly, WithinAbs(0.0, 0.001));
REQUIRE_THAT(sim->spacecraft[1].orbit.true_anomaly, WithinAbs(4.71238898038469, 0.001));
REQUIRE_THAT(sim->spacecraft[2].orbit.true_anomaly, WithinAbs(1.5707963267948966, 0.001));
destroy_simulation(sim);
}
@ -90,33 +81,33 @@ TEST_CASE("Calculate wait time for Hohmann transfer (lower to higher)", "[rendez
double r2 = vec3_magnitude(target->local_position);
SECTION("Zero angular separation - immediate transfer not possible") {
// If chaser is directly behind target, need to wait for target to move ahead
double angular_separation = 0.0;
double wait_time = calculate_wait_time_for_hohmann(r1, r2, angular_separation, earth->mass);
INFO("Wait time: " << wait_time << " s");
// Since lower orbit is faster, chaser will catch up, so wait time should be positive
REQUIRE_THAT(wait_time, WithinAbs(1358.16, 1.0));
// At 0 separation, chaser is faster and needs to be behind target
// Wait time is negative (should have burned already)
REQUIRE_THAT(wait_time, WithinAbs(-1358.16, 1.0));
}
SECTION("Small angular separation") {
double angular_separation = 0.5; // ~29 degrees
double angular_separation = 0.5;
double wait_time = calculate_wait_time_for_hohmann(r1, r2, angular_separation, earth->mass);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Wait time: " << wait_time << " s");
REQUIRE_THAT(wait_time, WithinAbs(-18192.7, 1.0));
REQUIRE_THAT(wait_time, WithinAbs(-20909.0, 1.0));
}
SECTION("Large angular separation (near 2π)") {
double angular_separation = 6.0; // ~344 degrees
SECTION("Large angular separation (near 2pi)") {
double angular_separation = 6.0;
double wait_time = calculate_wait_time_for_hohmann(r1, r2, angular_separation, earth->mass);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Wait time: " << wait_time << " s");
REQUIRE_THAT(wait_time, WithinAbs(12431.2, 1.0));
REQUIRE_THAT(wait_time, WithinAbs(9714.9, 1.0));
}
destroy_simulation(sim);
@ -145,22 +136,22 @@ TEST_CASE("Calculate wait time for Hohmann transfer (higher to lower)", "[rendez
double r2 = vec3_magnitude(target->local_position);
SECTION("Zero angular separation - target must catch up") {
// Higher orbit is slower, so target must catch up
double angular_separation = 0.0;
double wait_time = calculate_wait_time_for_hohmann(r1, r2, angular_separation, earth->mass);
INFO("Wait time: " << wait_time << " s");
REQUIRE_THAT(wait_time, WithinAbs(1414.46, 1.0));
// Higher orbit case: chaser is slower, needs to be ahead of target
REQUIRE_THAT(wait_time, WithinAbs(-1414.46, 1.0));
}
SECTION("Small angular separation") {
double angular_separation = 0.3; // ~17 degrees
double angular_separation = 0.3;
double wait_time = calculate_wait_time_for_hohmann(r1, r2, angular_separation, earth->mass);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Wait time: " << wait_time << " s");
REQUIRE_THAT(wait_time, WithinAbs(13586.2, 1.0));
REQUIRE_THAT(wait_time, WithinAbs(10757.3, 1.0));
}
destroy_simulation(sim);
@ -196,18 +187,18 @@ TEST_CASE("Calculate required separation for Hohmann transfer", "[rendezvous_hoh
double required_separation = calculate_required_separation_for_hohmann(r_lower, r_target, earth->mass);
INFO("Required separation: " << required_separation << " rad");
INFO("Required separation (deg): " << required_separation * 180.0 / M_PI << "°");
INFO("Required separation (deg): " << required_separation * 180.0 / M_PI << " deg");
REQUIRE_THAT(required_separation, WithinAbs(0.034734, 0.001));
REQUIRE_THAT(required_separation, WithinAbs(-0.034734, 0.001)); // Chaser faster, needs to be behind
}
SECTION("Higher to lower transfer") {
double required_separation = calculate_required_separation_for_hohmann(r_higher, r_target, earth->mass);
INFO("Required separation: " << required_separation << " rad");
INFO("Required separation (deg): " << required_separation * 180.0 / M_PI << "°");
INFO("Required separation (deg): " << required_separation * 180.0 / M_PI << " deg");
REQUIRE_THAT(required_separation, WithinAbs(-0.0348625, 0.001));
REQUIRE_THAT(required_separation, WithinAbs(0.0348625, 0.001)); // Chaser slower, needs to be ahead
}
SECTION("Equal radii - no transfer needed") {
@ -221,71 +212,363 @@ TEST_CASE("Calculate required separation for Hohmann transfer", "[rendezvous_hoh
destroy_simulation(sim);
}
SCENARIO("Complete Hohmann transfer phasing workflow", "[rendezvous_hohmann][workflow]") {
const double TIME_STEP = 10.0;
// ============================================================================
// New Test Cases for Validation and Next Wait Time
// ============================================================================
SimulationState* sim = create_simulation(3, 5, 10, TIME_STEP);
TEST_CASE("Validate Hohmann transfer parameters", "[rendezvous_hohmann][validation]") {
const double TIME_STEP = 30.0;
SimulationState* sim = create_simulation(3, 5, 10, TIME_STEP);
REQUIRE(load_system_config(sim, "tests/test_rendezvous_hohmann.toml"));
initialize_orbital_objects(sim);
int target_idx = find_spacecraft_by_name(sim, "Target_Satellite");
int chaser_lower_idx = find_spacecraft_by_name(sim, "Chaser_Lower");
Spacecraft* chaser_lower = &sim->spacecraft[1];
Spacecraft* chaser_higher = &sim->spacecraft[2];
Spacecraft* target = &sim->spacecraft[0];
CelestialBody* earth = &sim->bodies[0];
REQUIRE(target_idx >= 0);
REQUIRE(chaser_lower_idx >= 0);
double r_lower = vec3_magnitude(chaser_lower->local_position);
double r_higher = vec3_magnitude(chaser_higher->local_position);
double r_target = vec3_magnitude(target->local_position);
Spacecraft* target = &sim->spacecraft[target_idx];
Spacecraft* chaser = &sim->spacecraft[chaser_lower_idx];
SECTION("Valid lower to higher transfer") {
bool valid = validate_hohmann_transfer_parameters(r_lower, r_target, earth->mass);
INFO("Valid lower to higher: " << (valid ? "true" : "false"));
REQUIRE(valid == true);
}
SECTION("Valid higher to lower transfer") {
bool valid = validate_hohmann_transfer_parameters(r_higher, r_target, earth->mass);
INFO("Valid higher to lower: " << (valid ? "true" : "false"));
REQUIRE(valid == true);
}
SECTION("Equal radii - invalid (no relative motion)") {
bool valid = validate_hohmann_transfer_parameters(r_target, r_target, earth->mass);
INFO("Equal radii valid: " << (valid ? "true" : "false"));
REQUIRE(valid == false);
}
SECTION("Negative initial radius - invalid") {
bool valid = validate_hohmann_transfer_parameters(-1000.0, r_target, earth->mass);
INFO("Negative radius valid: " << (valid ? "true" : "false"));
REQUIRE(valid == false);
}
SECTION("Negative target radius - invalid") {
bool valid = validate_hohmann_transfer_parameters(r_lower, -1000.0, earth->mass);
INFO("Negative target radius valid: " << (valid ? "true" : "false"));
REQUIRE(valid == false);
}
SECTION("Zero central mass - invalid") {
bool valid = validate_hohmann_transfer_parameters(r_lower, r_target, 0.0);
INFO("Zero mass valid: " << (valid ? "true" : "false"));
REQUIRE(valid == false);
}
SECTION("Negative central mass - invalid") {
bool valid = validate_hohmann_transfer_parameters(r_lower, r_target, -1.0);
INFO("Negative mass valid: " << (valid ? "true" : "false"));
REQUIRE(valid == false);
}
destroy_simulation(sim);
}
TEST_CASE("Calculate relative orbit period", "[rendezvous_hohmann][phasing]") {
const double TIME_STEP = 30.0;
SimulationState* sim = create_simulation(3, 5, 10, TIME_STEP);
REQUIRE(load_system_config(sim, "tests/test_rendezvous_hohmann.toml"));
initialize_orbital_objects(sim);
Spacecraft* chaser_lower = &sim->spacecraft[1];
Spacecraft* chaser_higher = &sim->spacecraft[2];
Spacecraft* target = &sim->spacecraft[0];
CelestialBody* earth = &sim->bodies[0];
double r_lower = vec3_magnitude(chaser_lower->local_position);
double r_higher = vec3_magnitude(chaser_higher->local_position);
double r_target = vec3_magnitude(target->local_position);
SECTION("Lower to higher transfer") {
double rel_period = calculate_relative_orbit_period(r_lower, r_target, earth->mass);
INFO("Relative orbit period: " << rel_period << " s");
INFO("Relative orbit period: " << rel_period / 3600.0 << " h");
REQUIRE(rel_period > 0.0);
REQUIRE_THAT(rel_period, WithinAbs(245683.24, 1.0));
}
SECTION("Higher to lower transfer") {
double rel_period = calculate_relative_orbit_period(r_higher, r_target, earth->mass);
INFO("Relative orbit period: " << rel_period << " s");
INFO("Relative orbit period: " << rel_period / 3600.0 << " h");
REQUIRE(rel_period > 0.0);
REQUIRE_THAT(rel_period, WithinAbs(254924.71, 1.0));
}
SECTION("Very small radius difference - long period") {
double r1 = 6770000.0;
double r2 = 6771000.0;
double rel_period = calculate_relative_orbit_period(r1, r2, earth->mass);
INFO("Relative orbit period: " << rel_period << " s");
INFO("Relative orbit period: " << rel_period / 3600.0 / 24.0 << " days");
REQUIRE(rel_period > 0.0);
REQUIRE_THAT(rel_period, WithinAbs(25025208.27, 1.0));
}
SECTION("Large radius difference - short period") {
double r1 = 6571000.0;
double r2 = 7071000.0;
double rel_period = calculate_relative_orbit_period(r1, r2, earth->mass);
INFO("Relative orbit period: " << rel_period << " s");
INFO("Relative orbit period: " << rel_period / 3600.0 << " h");
REQUIRE(rel_period > 0.0);
REQUIRE_THAT(rel_period, WithinAbs(50889.08, 1.0));
}
destroy_simulation(sim);
}
TEST_CASE("Calculate next valid wait time for Hohmann transfer", "[rendezvous_hohmann][phasing]") {
const double TIME_STEP = 30.0;
SimulationState* sim = create_simulation(3, 5, 10, TIME_STEP);
REQUIRE(load_system_config(sim, "tests/test_rendezvous_hohmann.toml"));
initialize_orbital_objects(sim);
SECTION("Calculate and verify phasing for lower-to-higher transfer") {
double r1 = vec3_magnitude(chaser->local_position);
double r2 = vec3_magnitude(target->local_position);
Spacecraft* chaser_lower = &sim->spacecraft[1];
Spacecraft* chaser_higher = &sim->spacecraft[2];
Spacecraft* target = &sim->spacecraft[0];
CelestialBody* earth = &sim->bodies[0];
INFO("Chaser orbit radius: " << r1 << " m");
INFO("Target orbit radius: " << r2 << " m");
double r_lower = vec3_magnitude(chaser_lower->local_position);
double r_higher = vec3_magnitude(chaser_higher->local_position);
double r_target = vec3_magnitude(target->local_position);
// Calculate current angular separation
double current_sep = angular_distance(chaser->orbit.true_anomaly, target->orbit.true_anomaly);
SECTION("Lower to higher - positive wait time") {
double angular_separation = 0.0;
double next_wait = calculate_next_hohmann_wait_time(r_lower, r_target, angular_separation, earth->mass, TIME_STEP);
INFO("Current angular separation: " << current_sep << " rad");
INFO("Current angular separation (deg): " << current_sep * 180.0 / M_PI << "°");
INFO("Angular separation: " << angular_separation << " rad");
INFO("Next wait time: " << next_wait << " s");
INFO("Next wait time: " << next_wait / 3600.0 << " h");
// Calculate required separation for Hohmann
double required_sep = calculate_required_separation_for_hohmann(r1, r2, earth->mass);
REQUIRE(next_wait >= TIME_STEP);
REQUIRE_THAT(next_wait, WithinAbs(244325.08, 1.0));
}
INFO("Required separation: " << required_sep << " rad");
INFO("Required separation (deg): " << required_sep * 180.0 / M_PI << "°");
SECTION("Higher to lower - negative wait time becomes next cycle") {
double angular_separation = 0.0;
double next_wait = calculate_next_hohmann_wait_time(r_higher, r_target, angular_separation, earth->mass, TIME_STEP);
// Calculate wait time
double wait_time = calculate_wait_time_for_hohmann(r1, r2, current_sep, earth->mass);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Next wait time: " << next_wait << " s");
INFO("Next wait time: " << next_wait / 3600.0 << " h");
INFO("Wait time: " << wait_time << " s");
REQUIRE(next_wait >= TIME_STEP);
REQUIRE_THAT(next_wait, WithinAbs(253510.25, 1.0));
}
REQUIRE_THAT(wait_time, WithinAbs(-60062.651728, 0.1));
SECTION("Higher to lower - positive wait time (no adjustment needed)") {
double angular_separation = 0.3;
double next_wait = calculate_next_hohmann_wait_time(r_higher, r_target, angular_separation, earth->mass, TIME_STEP);
// Verify orbits are circular
REQUIRE_THAT(chaser->orbit.eccentricity, WithinAbs(0.0, 0.001));
REQUIRE_THAT(target->orbit.eccentricity, WithinAbs(0.0, 0.001));
INFO("Angular separation: " << angular_separation << " rad");
INFO("Next wait time: " << next_wait << " s");
REQUIRE(next_wait >= TIME_STEP);
REQUIRE_THAT(next_wait, WithinAbs(10757.30, 1.0));
}
SECTION("Calculate Hohmann transfer parameters") {
SECTION("At required separation - forced to next cycle by min_wait") {
double req_sep = calculate_required_separation_for_hohmann(r_lower, r_target, earth->mass);
double next_wait = calculate_next_hohmann_wait_time(r_lower, r_target, req_sep, earth->mass, TIME_STEP);
INFO("Required separation: " << req_sep << " rad");
INFO("Next wait time: " << next_wait << " s");
INFO("Next wait time: " << next_wait / 3600.0 << " h");
REQUIRE(next_wait >= TIME_STEP);
REQUIRE_THAT(next_wait, WithinAbs(245683.24, 1.0));
}
SECTION("Force skip to next cycle with large min_wait") {
double angular_separation = 0.5;
double min_wait = 30000.0;
double next_wait = calculate_next_hohmann_wait_time(r_lower, r_target, angular_separation, earth->mass, min_wait);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Min wait: " << min_wait << " s");
INFO("Next wait time: " << next_wait << " s");
REQUIRE(next_wait >= min_wait);
REQUIRE_THAT(next_wait, WithinAbs(224774.23, 1.0));
}
SECTION("Zero min_wait allows immediate transfer") {
double angular_separation = 0.3;
double next_wait = calculate_next_hohmann_wait_time(r_higher, r_target, angular_separation, earth->mass, 0.0);
INFO("Angular separation: " << angular_separation << " rad");
INFO("Next wait time: " << next_wait << " s");
REQUIRE(next_wait >= 0.0);
REQUIRE_THAT(next_wait, WithinAbs(10757.30, 1.0));
}
destroy_simulation(sim);
}
SCENARIO("Hohmann transfer rendezvous with validation", "[rendezvous_hohmann][integration]") {
const double TIME_STEP = 0.1;
SimulationState* sim = create_simulation(3, 5, 10, TIME_STEP);
REQUIRE(load_system_config(sim, "tests/test_rendezvous_hohmann.toml"));
int target_idx = find_spacecraft_by_name(sim, "Target_Satellite");
int chaser_lower_idx = find_spacecraft_by_name(sim, "Chaser_Lower");
REQUIRE(target_idx >= 0);
REQUIRE(chaser_lower_idx >= 0);
Spacecraft* target = &sim->spacecraft[target_idx];
Spacecraft* chaser = &sim->spacecraft[chaser_lower_idx];
CelestialBody* earth = &sim->bodies[0];
initialize_orbital_objects(sim);
SECTION("Execute validated Hohmann transfer and verify rendezvous") {
double r1 = vec3_magnitude(chaser->local_position);
double r2 = vec3_magnitude(target->local_position);
// Use existing calculate_hohmann_transfer from maneuver.h
HohmannTransfer hohmann = calculate_hohmann_transfer(r1, r2, earth->mass);
INFO("\n=== HOHMANN TRANSFER RENDZVOUS TEST ===");
INFO("Initial state:");
INFO(" Chaser: r=" << r1 << " m, nu=" << chaser->orbit.true_anomaly << " rad");
INFO(" Target: r=" << r2 << " m, nu=" << target->orbit.true_anomaly << " rad");
INFO("First burn delta-v: " << hohmann.dv1 << " m/s");
INFO("Second burn delta-v: " << hohmann.dv2 << " m/s");
INFO("Transfer time: " << hohmann.transfer_time << " s");
INFO("Target true anomaly: " << hohmann.true_anomaly_2 << " rad");
// Calculate angular separation
double angular_separation = chaser->orbit.true_anomaly - target->orbit.true_anomaly;
while (angular_separation > M_PI) angular_separation -= 2.0 * M_PI;
while (angular_separation < -M_PI) angular_separation += 2.0 * M_PI;
INFO(" Angular separation: " << angular_separation << " rad");
REQUIRE_THAT(hohmann.dv1, WithinAbs(28.699077, 0.01));
REQUIRE_THAT(hohmann.dv2, WithinAbs(28.592521, 0.01));
REQUIRE_THAT(hohmann.transfer_time, WithinAbs(2741.813778, 0.1));
// Validate parameters before proceeding
REQUIRE(validate_hohmann_transfer_parameters(r1, r2, earth->mass));
INFO(" Validation passed");
// Calculate Hohmann transfer parameters
HohmannTransfer hohmann = calculate_hohmann_transfer(r1, r2, earth->mass);
double wait_time = calculate_next_hohmann_wait_time(r1, r2, angular_separation, earth->mass, TIME_STEP);
double arrival_time = wait_time + hohmann.transfer_time;
INFO("\nTransfer parameters:");
INFO(" Transfer time: " << hohmann.transfer_time << " s");
INFO(" DV1 (departure): " << hohmann.dv1 << " m/s");
INFO(" DV2 (arrival): " << hohmann.dv2 << " m/s");
INFO(" Wait time: " << wait_time << " s");
INFO(" Arrival time: " << arrival_time << " s");
// Create departure maneuver
Maneuver departure = create_maneuver(
"Departure_Burn",
chaser_lower_idx,
BURN_PROGRADE,
hohmann.dv1,
TRIGGER_TIME,
wait_time
);
int dep_idx = add_maneuver_to_simulation(sim, &departure);
REQUIRE(dep_idx >= 0);
// Create arrival maneuver
Maneuver arrival = create_maneuver(
"Circularization_Burn",
chaser_lower_idx,
BURN_PROGRADE,
hohmann.dv2,
TRIGGER_TIME,
arrival_time
);
int arr_idx = add_maneuver_to_simulation(sim, &arrival);
REQUIRE(arr_idx >= 0);
// Dump initial state
dump_simulation_state(sim, "INITIAL STATE");
// Run simulation
double sim_time = 0.0;
const double DT = 1.0;
const int MAX_STEPS = 700000;
bool transfer_complete = false;
for (int i = 0; i < MAX_STEPS; i++) {
update_simulation(sim);
sim_time += DT;
// Dump state at key milestones
if (i == 0) {
dump_simulation_state(sim, "T=0 (initial)");
}
if (i == int(wait_time / DT)) {
dump_simulation_state(sim, "JUST BEFORE DEPARTURE");
}
if (i == int(wait_time / DT) + 1) {
dump_simulation_state(sim, "AFTER DEPARTURE BURN");
}
if (i == int(arrival_time / DT)) {
dump_simulation_state(sim, "JUST BEFORE ARRIVAL");
}
if (sim->maneuvers[arr_idx].executed && !transfer_complete) {
dump_simulation_state(sim, "AFTER ARRIVAL BURN");
transfer_complete = true;
break;
}
}
INFO("\n=== FINAL STATE ===");
INFO("Final time: " << sim_time << " s");
INFO("Departure executed: " << sim->maneuvers[dep_idx].executed);
INFO("Arrival executed: " << sim->maneuvers[arr_idx].executed);
dump_simulation_state(sim, "FINAL STATE");
// Verify maneuvers executed
REQUIRE(sim->maneuvers[dep_idx].executed);
REQUIRE(sim->maneuvers[arr_idx].executed);
// Verify rendezvous quality
double final_radius = vec3_magnitude(chaser->local_position);
double radius_error = fabs(final_radius - r2);
INFO("\nVerification:");
INFO(" Radius error: " << radius_error << " m");
INFO(" Chaser eccentricity: " << chaser->orbit.eccentricity);
Vec3 chaser_vel = chaser->local_velocity;
Vec3 target_vel = target->local_velocity;
double chaser_speed = vec3_magnitude(chaser_vel);
double target_speed = vec3_magnitude(target_vel);
Vec3 separation = vec3_sub(chaser->local_position, target->local_position);
double separation_distance = vec3_magnitude(separation);
double relative_velocity = vec3_magnitude(vec3_sub(chaser_vel, target_vel));
INFO(" Chaser speed: " << chaser_speed << " m/s");
INFO(" Target speed: " << target_speed << " m/s");
INFO(" Separation: " << separation_distance << " m");
INFO(" Relative velocity: " << relative_velocity << " m/s");
REQUIRE_THAT(radius_error, WithinAbs(10.0, 10.0));
REQUIRE_THAT(chaser->orbit.eccentricity, WithinAbs(0.0, 0.001));
REQUIRE_THAT(chaser_speed, WithinAbs(target_speed, 1.0));
REQUIRE_THAT(separation_distance, WithinAbs(0.0, 100.0));
}
destroy_simulation(sim);

Loading…
Cancel
Save