Skip to content
Draft
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
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ find_package_targets("${CMAKE_SOURCE_DIR}/simulation/sensors" SENSORS_TARGETS)
find_package_targets("${CMAKE_SOURCE_DIR}/simulation/simSynch" SIM_SYNCH_TARGETS)
find_package_targets("${CMAKE_SOURCE_DIR}/simulation/vizard" VIZ_INTERFACE_TARGETS)
find_package_targets("${CMAKE_SOURCE_DIR}/simulation/thermal" THERMAL_TARGETS)
find_package_targets("${CMAKE_SOURCE_DIR}/simulation/communication" COMMUNICATION_TARGETS)

if(NOT "${EXTERNAL_MODULES_PATH}" STREQUAL "")
string(REPLACE "\\" "/" EXTERNAL_MODULES_PATH "${EXTERNAL_MODULES_PATH}")
Expand All @@ -648,6 +649,7 @@ generate_package_targets("${SENSORS_TARGETS}" "${ARCHITECTURE_LIBS};" "simulatio
generate_package_targets("${SIM_SYNCH_TARGETS}" "${ARCHITECTURE_LIBS};" "simulation")
generate_package_targets("${VIZ_INTERFACE_TARGETS}" "${ARCHITECTURE_LIBS};" "simulation")
generate_package_targets("${THERMAL_TARGETS}" "${ARCHITECTURE_LIBS};" "simulation")
generate_package_targets("${COMMUNICATION_TARGETS}" "${ARCHITECTURE_LIBS};" "simulation")

# FSW ALGORITHMS
find_package_targets("${CMAKE_SOURCE_DIR}/fswAlgorithms/attControl" ATT_CONTROL_TARGETS)
Expand Down
49 changes: 49 additions & 0 deletions src/architecture/msgPayloadDefC/AntennaOutMsgPayload.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
ISC License

Copyright (c) 2025, Departement of Engineering Cybernetics, NTNU,

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/
#include <stdint.h>

#include <stdint.h>

#ifndef antennaOutMsg_H
#define antennaOutMsg_H

/*! antenna state message definition */
typedef struct {
char antennaID[20]; //!< -- Antenna identifier
uint32_t environment; //!< -- Environment around the antenna (0: space, 1: ground)
uint32_t antennaState; //!< -- Current state of the antenna (0: off, 1: Rx, 2: Tx, 3: RxTx)
double frequency; //!< [Hz] Operating frequency of the antenna
double B; //!< [Hz] Frequency bandwidth of the antenna
double HPBW_az; //!< [rad] Half-power beamwidth in azimuth
double HPBW_el; //!< [rad] Half-power beamwidth in elevation
double P_Tx; //!< [W] Transmit power
double P_Rx; //!< [W] Receive power
double GdB; //!< [dB] Antenna gain in decibels
double P_N; //!< [W] Noise power at the receiver
double P_eirp_dB; //!< [W] EIRP power transmitted
double G_TN; //!< [dB/K] Antenna gain over system noise temperature
double T_Ambient; //!< [K] Ambient temperature around the antenna
double r_AN_N[3]; //!< [m] Position vector {N} -> {A} of the antenna, decomposed in {N} frame
double sigma_NA[3]; //!< -- MRP attitude of antenna relative to inertial frame {N}
double v_AN[3]; //!< [m/s] Velocity vector from antenna to ground station in inertial frame {N}
double r_AP_N[3]; //!< -- Position vector of the antenna wrt to the celestial body frame {P} decomposed in {N} (used for ground antennas only)
double r_AP_P[3]; //!< -- Position vector of the antenna wrt to the celestial body frame {P} decomposed in {P} (used for ground antennas only)
double nhat_LP_N[3]; //!< -- Surface normal vector from the target location in inertial coordinates (used for ground antennas only)
}AntennaOutMsgPayload;
#endif /* antennaOutMsg_H */
29 changes: 29 additions & 0 deletions src/architecture/msgPayloadDefC/AntennaStateMsgPayload.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
ISC License

Copyright (c) 2025, Departement of Engineering Cybernetics, NTNU, Norway

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/

#ifndef antennaStateMsg_H
#define antennaStateMsg_H

#include <stdint.h>

/*! antenna state message definition */
typedef struct {
uint32_t antennaState; //!< Current antenna state TODO shouldnt that be an enum?
}AntennaStateMsgPayload;
#endif /* antennaStateMsg_H */
5 changes: 3 additions & 2 deletions src/architecture/msgPayloadDefC/GroundStateMsgPayload.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
/*! @brief Message that defines the inertial location of a groundLocation at the current time.
*/
typedef struct {
double r_LN_N[3]; //!< Position vector of the location w.r.t. the inertial origin in the inertial frame
double r_LP_N[3]; //!< Position vector of the location with respect to the planet center in the inertial frame
double r_LN_N[3]; //!< Position vector of the location w.r.t. the inertial origin in the inertial frame
double r_LP_N[3]; //!< Position vector of the location with respect to the planet center in the inertial frame
double rhat_LP_N[3]; //!< [-] Surface normal vector from the target location in inertial coordinates
}GroundStateMsgPayload;


Expand Down
36 changes: 36 additions & 0 deletions src/architecture/msgPayloadDefC/LinkBudgetOutMsgPayload.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
ISC License

Copyright (c) 2025, Departement of Engineering Cybernetics, NTNU

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/
#include <stdint.h>

#ifndef linkBudgetOutMsg_H
#define linkBudgetOutMsg_H

/*! antenna state message definition */
typedef struct {
char antennaID1[20]; //!< -- Antenna identifier
char antennaID2[20]; //!< -- Antenna identifier
uint32_t antennaState2; //!< -- Current state of the antenna 2 (0: off, 1: Rx, 2: Tx, 3: RxTx)
uint32_t antennaState1; //!< -- Current state of the antenna 1 (0: off, 1: Rx, 2: Tx, 3: RxTx)
double CNR1; //!< [-] Carrier to noise ratio at antenna 1
double CNR2; //!< [-] Carrier to noise ratio at antenna 2
double distance; //!< [m] Distance between the two antennas
double bandwidth; //!< [Hz] Bandwidth of the communication link
double frequency; //!< [Hz] Operating frequency of the communication link
}LinkBudgetOutMsgPayload;
#endif /* linkBudgetOutMsg_H */
156 changes: 156 additions & 0 deletions src/architecture/utilities/ItuRefAtmosphere.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
ISC License

Copyright (c) 2025, Departement of Engineering Cybernetics, NTNU

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/

#include "architecture/utilities/ItuRefAtmosphere.h"
#include <cmath>
#include <algorithm>

// Constructor
ItuAtmosphere::ItuAtmosphere() {
}

// Destructor
ItuAtmosphere::~ItuAtmosphere() {
}
const ItuAtmosphere& ItuAtmosphere::instance() {
static ItuAtmosphere inst;
return inst;
}

// Getters
double ItuAtmosphere::getTempISA(double altitude_m) {
return instance().calcTempISA(altitude_m);
}

double ItuAtmosphere::getPresISA(double altitude_m) {
return instance().calcPresISA(altitude_m);
}

double ItuAtmosphere::getWaterVapDensityISA(double altitude_m) {
return instance().calcWaterVapDensityISA(altitude_m);
}

size_t ItuAtmosphere::findLayerIndex(double altitude_m) const {
size_t layer_idx = NUM_LAYERS - 1;
for (size_t i = 0; i < NUM_LAYERS - 1; ++i) {
if (altitude_m >= ATMOSPHERE_DATA[i].h &&
altitude_m < ATMOSPHERE_DATA[i + 1].h)
{
layer_idx = i;
break;
}
}
return layer_idx;
}

double ItuAtmosphere::geometricHeight(double altitude_m) const {
// For altitudes above 84.852 km, convert geopotential height to geometric height
return (R_EARTH_ITU * altitude_m * 1e-3) / (R_EARTH_ITU - altitude_m*1e-3); // ITU-R P.835-7 eq 1b
}

/* Calculate Temperature according to ITU-R P.835-7
*/
double ItuAtmosphere::calcTempISA(double altitude_m) const {
// Clamp above model validity (85 km)
if (altitude_m >= ATMOSPHERE_DATA[NUM_LAYERS - 1].h) {
// if h above 84.852 km
double Z = ItuAtmosphere::geometricHeight(altitude_m); // [km] Geometric height
if (Z < 91.0) {
return 186.8673; // [K] Constant temperature between 84.852 km and 91 km (ITU-R P.835-7 eq 4a)
} else if (Z < 100.0) {
return 263.1905 - 76.3232 * std::sqrt(1 - std::pow((Z - 91.0)/(19.9429),2)); // [K] Linear increase between 91 km and 100 km (ITU-R P.835-7 eq 4b)
} else {
return 195.08134; // [K] Above 100 km, assume constant temperature
}
}

// Find which layer the altitude falls into (table in header file)
size_t layer_idx = ItuAtmosphere::findLayerIndex(altitude_m);

// Compute temperature at layer base: T_(layer_idx-1)
double Ti = T0;
for (size_t i = 0; i < layer_idx; ++i) {
double h0 = ATMOSPHERE_DATA[i].h; // [m] Altitude at layer "i" base
double h1 = ATMOSPHERE_DATA[i + 1].h; // [m] Altitude at layer "i+1" base
double dT_dh_i = ATMOSPHERE_DATA[i].dT_dh; // [K/km] Temperature gradient in layer "i"
Ti += dT_dh_i * (h1 - h0) * 1e-3; // [K] Temperature at top of layer "layer_idx-1"
}

// Linear variation within that layer
double Hi = ATMOSPHERE_DATA[layer_idx].h; // [m] Altitude at layer "layer_idx" base
double dT_dh = ATMOSPHERE_DATA[layer_idx].dT_dh; // [K/km] Temperature gradient in layer "layer_idx"

return Ti + dT_dh * (altitude_m - Hi) * 1e-3; // [](ITU-R P.835-2 eq 2)
}

/* Calculate Pressure according to ITU-R P.835-7
* barometric formula for each atmospheric layer
*/
double ItuAtmosphere::calcPresISA(double altitude_m) const {
// Find which layer the altitude falls into
size_t layer_idx = ItuAtmosphere::findLayerIndex(altitude_m);
double dT_dh = ATMOSPHERE_DATA[layer_idx].dT_dh;
if (layer_idx == 0) {
// 0 km < altitude < 11 km
return 1013.25 * pow((288.15 / (288.15 - (dT_dh * altitude_m * 1e-3))), -itu_press_const/dT_dh); // ITU-R P.835-7 eq 3a
} else if (layer_idx == 1) {
// 11 km < altitude < 20 km
return 226.3226 * exp(-0.157688 * (altitude_m * 1e-3 - 11.0)); // ITU-R P.835-7 eq 3b
} else if (layer_idx == 2) {
// 20 km < altitude < 32 km
return 54.7498 * pow((216.65 / (216.65 + (altitude_m * 1e-3 - 20.0))), -itu_press_const); // ITU-R P.835-7 eq 3c
} else if (layer_idx == 3) {
// 32 km < altitude < 47 km
return 8.680422 * pow((228.65 / (228.65 + (dT_dh * (altitude_m * 1e-3 - 32.0)))), -itu_press_const/dT_dh); // ITU-R P.835-7 eq 3d
} else if (layer_idx == 4) {
// 47 km < altitude < 51 km
return 1.109106 * exp(-0.126226 * (altitude_m * 1e-3 - 47.0)); // ITU-R P.835-7 eq 3e
} else if (layer_idx == 5) {
// 51 km < altitude < 71 km
return 0.6694167 * pow((270.65 / (270.65 - (dT_dh * (altitude_m * 1e-3 - 51.0)))), -itu_press_const/dT_dh); // ITU-R P.835-7 eq 3f
} else if (layer_idx == 6) {
// 71 km < altitude < 85 km
return 0.03956649 * pow((214.65 / (214.65 - (dT_dh * (altitude_m * 1e-3 - 71.0)))), -itu_press_const/dT_dh); // ITU-R P.835-7 eq 3g
} else {
// altitude >= 85 km
double Z = ItuAtmosphere::geometricHeight(altitude_m); // [km] Geometric height
if (Z < 100.0e3) {
return exp(95.571899 - 4.011801*Z + 6.424731*Z*Z*1e-2 - 4.789660*Z*Z*Z*1e-4 + 1.340543*Z*Z*Z*Z*1e-6); // ITU-R P.835-7 eq 5
} else {
return 0.0; // Pressure above 100 km is assumed zero
}
}
}

/* Calculate Water Vapor Density according to ITU-R P.835-7
* Uses exponential decay model with different scale heights
*/
double ItuAtmosphere::calcWaterVapDensityISA(double altitude_m) const {
// Calculate geometric height
double Z = ItuAtmosphere::geometricHeight(altitude_m); // [km] Geometric height
double rho = rho0 * std::exp(-Z / h0_water); // [g/m3] ITU-R P.835-2 eq 6
double T_Z = ItuAtmosphere::calcTempISA(altitude_m); // [K]
double e_z = (rho*T_Z)/(216.7); // [hPa] Partial pressure at height Z
double p_z = ItuAtmosphere::calcPresISA(altitude_m); // [hPa] Total pressure at height Z
if (e_z/p_z < 2.0e-6) {
// Use ITU-R 835-7 eq. 8
rho = 2.0e-6 * (p_z * 216.7)/(T_Z); // [g/m3]
}
return rho;
}
95 changes: 95 additions & 0 deletions src/architecture/utilities/ItuRefAtmosphere.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
ISC License

Copyright (c) 2025, Departement of Engineering Cybernetics, NTNU

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/


#ifndef ITU_ATMOSPHERE_H
#define ITU_ATMOSPHERE_H

#include <cmath>
#include <algorithm>

/*! @brief ITU-R P.835-2 Reference Standard Atmosphere Implementation
*
* This class implements the mean annual global reference atmosphere as specified
* in ITU-R P.835-2 recommendation for calculating gaseous attenuation along Earth-space paths.
* The class precomputes atmospheric properties at initialization and proviedes lookup values at runtime.
*/
class ItuAtmosphere {
public:
ItuAtmosphere();
~ItuAtmosphere();

// Static methods for accessing atmospheric properties during runtime
static double getTempISA(double altitude); // Temperature in [K]
static double getPresISA(double altitude); // Pressure in [hPa]
static double getWaterVapDensityISA(double altitude); // Water vapor density in [g/m3]

private:
size_t findLayerIndex(double altitude_m) const;
double geometricHeight(double altitude_m) const;
double calcTempISA(double altitude_m) const;
double calcPresISA(double altitude_m) const;
double calcWaterVapDensityISA(double altitude) const;

public:

private:
// ITU-R P.835-7 constants ("gas constant" * "molar mass of air" / "gravity")
// -> 9.80665[m/s2] * 28.9645[g/mol] / 8.31446[J/(mol*K)] = 34.1627[g*K/(m*s2)]
static constexpr double itu_press_const = 34.1632; // [K/km]

// Atmosphere layer structure
struct AtmosphereLayer {
double h; // Altitude Hi (km)
double dT_dh; // Temperature gradient Li (K/km)
};

// Constants for the mean annual global reference atmosphere (ITU-R P.835-2, Table 1)
static constexpr size_t NUM_LAYERS = 8;

// Atmosphere layers data according to ITU-R P.835-2 (Table 1)
static constexpr AtmosphereLayer ATMOSPHERE_DATA[NUM_LAYERS] = {
{ 0.0e3, -6.5}, // [m, K/km] 0 - 11 km
{ 11.0e3, 0.0}, // [m, K/km] 11 - 20 km
{ 20.0e3, 1.0}, // [m, K/km] 20 - 32 km
{ 32.0e3, 2.8}, // [m, K/km] 32 - 47 km
{ 47.0e3, 0.0}, // [m, K/km] 47 - 51 km
{ 51.0e3, -2.8}, // [m, K/km] 51 - 71 km
{ 71.0e3, -2.0}, // [m, K/km] 71 - 85 km
{ 84.852e3, 0.0} // [m, K/km] Above 85 km (gradient not used beyond this assume const temp)
};

// Ground-level standard conditions (ITU-R P.835-2, equation 5)
static constexpr double T0 = 288.15; // [K] Standard temperature at sea level (ITU-R P.835-2 eq 5)
static constexpr double P0 = 1013.25; // [hPa] Standard pressure at sea level (ITU-R P.835-2 eq 5)
static constexpr double rho0 = 7.5; // [g/m³] Standard water vapor density at sea level (ITU-R P.835-2 eq 7)

// Scale heights for exponential profiles
static constexpr double h0_water = 2.0; // [km] Water vapor scale height (ITU-R P.835-7 eq 6)
// static constexpr double h0_dry = 6.0; // [km] Dry atmosphere scale height (ITU-R P.835-2 eq 9)

static constexpr double R_EARTH_ITU = 6356.766; // [km] Earth's radius for ITU atmosphere calculations

ItuAtmosphere(const ItuAtmosphere&) = delete;
ItuAtmosphere& operator=(const ItuAtmosphere&) = delete;

// Singleton instance
static const ItuAtmosphere& instance();
};
#endif /* ITU_ATMOSPHERE_H */
Loading
Loading