qtrocket2/tests/test_rocket_simulator.cpp
2025-04-20 12:29:36 -06:00

107 lines
3.1 KiB
C++

// tests/test_rocket_simulator.cpp
#include "vendor/catch_amalgamated.hpp"
#include "Rocket.h"
#include "Stage.h"
#include "Motor.h"
#include "Airframe.h"
#include "FinSet.h"
#include "RecoverySystem.h"
#include "Environment.h"
#include "FlightSimulator.h"
#include "FlightState.h"
#include "Integrator.h"
// Bring Approx into scope
using Catch::Approx;
TEST_CASE("Rocket and FlightSimulator integration test", "[integration]") {
// Setup Environment
auto environment = std::make_shared<Environment>(
101325.0, // surface pressure (Pa)
288.15, // surface temperature (K)
0.0 // launch altitude (m)
);
// Setup Rocket
auto rocket = std::make_shared<Rocket>("IntegrationTestRocket");
auto stage = std::make_unique<Stage>("Stage1");
// Motor
auto motor = std::make_unique<Motor>("TestMotor", 0.05, 50.0); // 50g propellant
motor->addThrustDataPoint(0.0, 0.0);
motor->addThrustDataPoint(0.1, 50.0);
motor->addThrustDataPoint(1.5, 50.0);
motor->addThrustDataPoint(1.6, 0.0);
stage->addMotor(std::move(motor));
// Airframe
auto airframe = std::make_unique<Airframe>("Airframe1",
1.5, // length
0.1, // diameter
2.0, // dry mass
0.75 // drag coefficient
);
stage->setAirframe(std::move(airframe));
// FinSet
auto finset = std::make_unique<FinSet>("TestFins",
3, // 3 fins
0.15, // root chord
0.10, // tip chord
0.10, // span
0.05, // sweep
0.003, // thickness
500.0 // density
);
stage->setFinSet(std::move(finset));
// Recovery
auto recovery = std::make_unique<RecoverySystem>("MainChute",
RecoverySystem::DeploymentType::Apogee,
0.0, // no trigger value needed
1.5, // Cd
2.0 // area
);
stage->setRecoverySystem(std::move(recovery));
rocket->addStage(std::move(stage));
rocket->updateMassProperties();
// Setup FlightSimulator
FlightSimulator simulator(rocket, environment);
SECTION("Full flight simulation runs and reaches apogee") {
simulator.run(20.0, 0.01); // Simulate 20 seconds with 10ms step
const auto& flightLog = simulator.getFlightLog();
REQUIRE(flightLog.size() > 0);
double maxAltitude = 0.0;
double landingAltitude = flightLog.back().getPosition()[2];
for (const auto& state : flightLog) {
double alt = state.getPosition()[2];
if (alt > maxAltitude) {
maxAltitude = alt;
}
}
REQUIRE(maxAltitude > 0.0); // Rocket climbed
REQUIRE(landingAltitude <= 1.0); // Rocket landed (near ground)
// Optional: check that apogee was reached early in flight
size_t apogeeIndex = 0;
for (size_t i = 1; i < flightLog.size(); ++i) {
if (flightLog[i].getPosition()[2] < flightLog[i-1].getPosition()[2]) {
apogeeIndex = i - 1;
break;
}
}
REQUIRE(apogeeIndex > 0); // Apogee was found
}
}