![]() |
WarpTwin
Documentation for WarpTwin models and classes.
|
/******************************************************************************
* Copyright (c) ATTX INC 2025. All Rights Reserved.
*
* This software and associated documentation (the "Software") are the
* proprietary and confidential information of ATTX INC. The Software is
* furnished under a license agreement between ATTX and the user organization
* and may be used or copied only in accordance with the terms of the agreement.
* Refer to 'license/attx_license.adoc' for standard license terms.
*
* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
* transmitted in any form or by any means, for any purpose, without the express
* written permission of ATTX INC.
******************************************************************************/
/*
Spacecraft model header file
Author: Alex Reynolds
*/
/*
Metadata for MS GUI:
imdata = {"displayname" : "Spacecraft",
"exclude" : False,
"category" : "Assemblies"
}
aliases = {"initial_position" : "Initial Position",
"initial_velocity" : "Initial Velocity",
"pos_vel_init_frame" : "EXCLUDE",
"initial_attitude" : "Initial Attitude",
"initial_ang_vel" : "Initial Ang. Vel.",
"att_init_frame" : "EXCLUDE",
"planet_configuration" : "Planet Information",
"planet_inertial_frame" : "Planet Inertial Frame",
"planet_rotating_frame" : "Planet Rotating Frame",
"body" : "Spacecraft Body",
"lvlh" : "Spacecraft LVLH Frame",
"pos_sc_pci" : "Position",
"vel_sc_pci" : "Velocity",
"quat_sc_pci" : "Attitude",
"ang_vel_sc_pci__body" : "Ang. Vel.",
"latitude_detic" : "Latitude",
"longitude" : "Longitude",
"altitude_detic" : "Altitude",
"planet_ptr" : "Planet",
"inertia" : "EXCLUDE",
"mass" : "Mass"
}
*/
#ifndef MODELS_ASSEMBLIES_SPACECRAFT_H
#define MODELS_ASSEMBLIES_SPACECRAFT_H
#include "core/CartesianVector.hpp"
#include "frames/Body.h"
#include "frames/Node.h"
#include "models/states/FrameStateSensorModel.h"
#include "models/environment/AsphericalGravityModel.h"
#include "models/environment/SphericalHarmonicsGravityModel.h"
#include "models/assemblies/CustomPlanet.h"
#include "models/assemblies/SpicePlanet.h"
#include "models/states/PlanetRelativeStatesModel.h"
#include "models/environment/GravityGradientModel.h"
#include "models/support/LvlhFrameManagerModel.h"
#include "models/actuators/TimedImpulsiveBurnModel.h"
#include "constants/planetdefaults.h"
#include "models/environment/MSISAtmosphereModel.h"
#include "models/actuators/FlatPlateDragModel.h"
namespace warptwin {
class Executive;
/**
* @brief Spacecraft Model
*
* The spacecraft model is a convenient wrapper around a set of high-fidelity
* models to make building space-based simulation easy. This class is ideal
* for configuring a simple planet orbiter.
*
* Default models wrapped into the spacecraft model include:
* - Gravity with J2 and J3 effects
* - Gravity gradient torque
* - Planet rotating state sensor (latitude/longitude/altitude state)
* - Earth only: MSIS atmospheric drag
*
* Spacecraft comes with two frames
*
* To configure spacecraft, users must assign the spacecraft planet_ptr to
* point to a valid instance of CustomPlanet or SpicePlanet.
*/
MODEL(Spacecraft)
public:
// Model params
// NAME TYPE DEFAULT VALUE
START_PARAMS
/** This is the mass of the spacecraft, in the same units as the rest of the
* simulation. Default is 1 kg. */
SIGNAL(mass, double, 1.0)
/** This is the body inertia tensor of the spacecraft, in the same units as the rest of the
* simulation. Default is identity matrix. */
SIGNAL(inertia, Matrix3, Matrix3({{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}))
/** The position of the spacecraft in the initialization frame, expressed in init frame.
Default behavior is to take input in meters. */
SIGNAL(initial_position, CartesianVector3, CartesianVector3({0.0,0.0,0.0}))
/** The velocity of the spacecraft in the initialization frame, expressed in init frame
Default behavior is to take input in meters/sec. */
SIGNAL(initial_velocity, CartesianVector3, CartesianVector3({0.0,0.0,0.0}))
/** The frame in which position and velocity are initialized. If not set, defaults to planet inertial frame */
SIGNAL(pos_vel_init_frame, Frame*, nullptr)
/** The attitude of the spacecraft relative to the initialization frame. */
SIGNAL(initial_attitude, clockwerk::Quaternion, clockwerk::Quaternion({1.0,0.0,0.0,0.0}))
/** The angular velocity of the spacecraft relative to the initialization frame, expressed
* in spacecraft body frame.*/
SIGNAL(initial_ang_vel, CartesianVector3, CartesianVector3({0.0,0.0,0.0}))
/** The frame in which attitude and angular velocity are initialized. If not set, defaults to planet inertial frame */
SIGNAL(att_init_frame, Frame*, nullptr)
/** A pointer to the planet object, which may be either CustomPlanet or SpicePlanet.
* This variable must be set, and is cast to a planet internally within the spacecraft
* model. From the planet, all configuration parameters for gravity and planet relative
* state models are set. */
SIGNAL(planet_ptr, GraphTreeObject*, nullptr)
END_PARAMS
// Model inputs
// NAME TYPE DEFAULT VALUE
START_INPUTS
END_INPUTS
// Model outputs
// NAME TYPE DEFAULT VALUE
START_OUTPUTS
/** Accessor to the inertial frame of the planet. Set to point to _planet_inertial in constructor. */
SIGNAL(body, Frame*, nullptr)
/** Accessor to the rotating frame of the planet. Set to point to _planet_inertial in constructor. */
SIGNAL(lvlh, Frame*, nullptr)
/** Position wrt planet centered inertial frame. Default is in meters. */
SIGNAL(pos_sc_pci, CartesianVector3, CartesianVector3({0.0, 0.0, 0.0}))
/** Velocity wrt planet centered inertial frame. Default is in meters/sec */
SIGNAL(vel_sc_pci, CartesianVector3, CartesianVector3({0.0, 0.0, 0.0}))
/** Attitude quaternion wrt planet inertial frame */
SIGNAL(quat_sc_pci, clockwerk::Quaternion, clockwerk::Quaternion({1.0, 0.0, 0.0, 0.0}))
/** Angular velocity of the spacecraft wrt planet, output in body frame. In rad/s */
SIGNAL(ang_vel_sc_pci__body, CartesianVector3, CartesianVector3({0.0, 0.0, 0.0}))
/** The latitude of the spacecraft wrt planet rotating frame, in radians */
SIGNAL(latitude_detic, double, 0.0)
/** The longitude of the spacecraft wrt the planet rotating frame, in radians */
SIGNAL(longitude, double, 0.0)
/** The altitude of the spacecraft wrt planet ellipsoid. Default is in meters */
SIGNAL(altitude_detic, double, 0.0)
/** The total power input from all sources, in Watts */
SIGNAL(total_power_in, double, 0.0)
/** The total power output from all sources, in Watts */
SIGNAL(total_power_out, double, 0.0)
END_OUTPUTS
/// @brief Initialize position and velocity of the spacecraft body frame
/// @param position_sc_frame__frame The desired position of the spacecraft body wrt frame_ptr
/// @param velocity_sc_frame__frame The desired velocity of the spacecraft body represented in frame frame_ptr
/// @param frame_ptr The frame relative to which state is initialized. Default (nullptr) will init wrt sim root frame
/// @return Error code corresponding to success/failure
/// @note Overloaded to init via string or frame
int initializePositionVelocity(CartesianVector3 position_sc_frame__frame,
CartesianVector3 velocity_sc_frame__frame,
Frame* frame_ptr=nullptr);
/// @brief Initialize position and velocity of the spacecraft body frame
/// @param position_sc_frame__frame The desired position of the spacecraft body wrt frame_ptr
/// @param velocity_sc_frame__frame The desired velocity of the spacecraft body represented in frame frame_ptr
/// @param frame_name The name of the frame relative to which state should be initialized
/// @return Error code corresponding to success/failure
/// @note Overloaded to init via string or frame
int initializePositionVelocity(CartesianVector3 position_sc_frame__frame,
CartesianVector3 velocity_sc_frame__frame,
const std::string &frame_name);
/// @brief Function to initialize the spacecraftrelative to planet from orbital elements
/// @param a Semimajor axis, m
/// @param e Orbit eccentricity
/// @param i Orbit inclination, radians
/// @param RAAN Orbit RAAN, radians
/// @param w Orbit argument of periapsis, radians
/// @param f Orbit true anomaly, radians
/// @return Error code corresponding to success/failure
/// @note Assumes that the spacecraft planet has been set and initializes using orbital elements
/// relative to the configured planet.
/// @note Sets the spacecraft's parent to the planet inertial frame implicitly. Do not use this
/// function if you are not ok with that.
int initializeFromOrbitalElements(double a, double e, double i, double RAAN, double w, double f);
/// @brief Initialize attitude and angular velocity of the spacecraft body frame
/// @param quat_sc_frame__frame The desired attitude of the spacecraft body wrt frame_ptr
/// @param ang_vel_sc_frame__sc The desired angular velocity of the spacecraft body wrt frame_ptr in the sc body frame
/// @param frame_ptr The frame relative to which state is initialized. Default (nullptr) will init wrt sim root frame
/// @return Error code corresponding to success/failure
/// @note Overloaded to init via string or frame
int initializeAttitude(clockwerk::Quaternion quat_sc_frame__frame,
CartesianVector3 ang_vel_sc_frame__sc,
Frame* frame_ptr=nullptr);
/// @brief Initialize attitude and angular velocity of the spacecraft body frame
/// @param quat_sc_frame__frame The desired attitude of the spacecraft body wrt frame_ptr
/// @param ang_vel_sc_frame__sc The desired angular velocity of the spacecraft body wrt frame_ptr in the sc body frame
/// @param frame_name The name of the frame relative to which state should be initialized
/// @return Error code corresponding to success/failure
/// @note Overloaded to init via string or frameFrame* frame_ptr=nullptr
int initializeAttitude(clockwerk::Quaternion quat_sc_frame__frame,
CartesianVector3 ang_vel_sc_frame__sc,
const std::string &frame_name);
/// @brief Function to program a timed impulsive burn into the spacecraft
/// @param delta_v__f The impulsive burn vector to execute
/// @param time_string Time string in an acceptable SPICE format at which burn should occur
/// @param force_frame_ptr The frame in which the burn should be executed
/// @return Pointer to the impulse model
warptwin::TimedImpulsiveBurnModel* programManeuver(CartesianVector3 delta_v__f,
std::string time_string,
Frame* force_frame_ptr);
/// @brief Function to program a timed impulsive burn into the spacecraft
/// @param delta_v__f The impulsive burn vector to execute
/// @param sim_time The time at which the burn should occur
/// @param force_frame_ptr The frame in which the burn should be executed
/// @return Pointer to the impulse model
warptwin::TimedImpulsiveBurnModel* programManeuver(CartesianVector3 delta_v__f,
double sim_time,
Frame* force_frame_ptr);
/// @brief Add a power load to the spacecraft
/// @param power_load_ptr Pointer to the power load (Watts) to add
/// @return Error code corresponding to success/failure
/// @note The value within the DataIOBase pointer must be a double
int addPowerLoad(clockwerk::DataIO<double>* power_load_ptr);
/// @brief Clear the list of power loads
void clearPowerLoads() {_power_load_ptrs.clear();}
/// @brief Add a power source to the spacecraft
/// @param power_source_ptr Pointer to the power source (Watts) to add
/// @return Error code corresponding to success/failure
/// @note The value within the DataIOBase pointer must be a double
int addPowerSource(clockwerk::DataIO<double>* power_source_ptr);
/// @brief Clear the list of power sources
void clearPowerSources() {_power_source_ptrs.clear();}
// Accessor for our spacecraft body
clockwerk::DataIO<Body*> body = clockwerk::DataIO<Body*>(this, "body", &_body);
// Accessor for our spacecraft lvlh frame
clockwerk::DataIO<Body*> lvlh = clockwerk::DataIO<Body*>(this, "lvlh", nullptr);
/// @brief Function to get a handle to the frame state sensor relative to the planet inertial frame
/// @return Pointer to the planet inertial frame state sensor
warptwin::FrameStateSensorModel* planetInertialStateSensor() {return &_planet_inertial_state_sensor;}
/// @brief Function to get a handle to the frame state sensor relative to the planet rotating frame
/// @return Pointer to the planet rotating frame state sensor
warptwin::FrameStateSensorModel* planetRotatingStateSensor() {return &_planet_rotating_state_sensor;}
/// @brief Function to get a handle to the LVLH frame manager contained within this model
/// @return Pointer to the LVLH frame manager
warptwin::LvlhFrameManagerModel* lvlhFrameManager() {return &_lvlh_frame_manager;}
/// @brief Function to get a handle to the aspherical gravity model contained within this model
/// @return Pointer to the aspherical gravity model
/// @note Returns nullptr if aspherical gravity is not the active gravity model
warptwin::AsphericalGravityModel* asphericalGravityModel() {return _asp_ptr;}
/// @brief Function to get a handle to the spherical harmonics gravity model contained within this model
/// @return Pointer to the spherical harmonics gravity model
/// @note Returns nullptr if spherical harmonic gravity is not the active gravity model
warptwin::SphericalHarmonicsGravityModel* sphericalHarmGravityModel() {return _sph_ptr;}
/// @brief Function to get a handle to the planet relative state model contained within this model
/// @return Pointer to the planet relative state sensor model
warptwin::PlanetRelativeStatesModel* planetRelativeModel() {return &_planet_relative;}
/// @brief Function to get a handle to the gravity gradient model contained within this model
/// @return Pointer to the gravity gradient model
warptwin::GravityGradientModel* gravityGradientModel() {return &_gravity_gradient;}
/// @brief Function to get a handle to the MSIS atmosphere model contained within this model
/// @return Pointer to the MSIS atmosphere model
/// @note Returns nullptr if MSIS atmosphere model is not active
warptwin::MSISAtmosphereModel* msisModel() {return _msis_ptr;}
/// @brief Function to get a handle to the flat plate drag model contained within this model
/// @return Pointer to the flat plate drag model
warptwin::FlatPlateDragModel* atmosDrag() {return &_atmos_drag;}
protected:
int16 start() override;
int16 execute() override;
/// @brief Configure the spacecraft class to map to planet
/// @return Error code corresponding to success/failure
int _configureFromPlanet();
/// @brief Function to internally map relationships between sensors
void _mapInternal();
/// @brief Sum the power loads and sources to calculate power accumulation
void _calculatePowerAccumulation();
// Spacecraft body
Body _body;
Node _gravity_node;
Node _drag_node;
// Models included within the Spacecraft class
FrameStateSensorModel _planet_inertial_state_sensor;
FrameStateSensorModel _planet_rotating_state_sensor;
LvlhFrameManagerModel _lvlh_frame_manager;
GravityGradientModel _gravity_gradient;
PlanetRelativeStatesModel _planet_relative;
FlatPlateDragModel _atmos_drag;
// Pointers to models which are declared on the basis of the spacecraft
// model type
AsphericalGravityModel* _asp_ptr = nullptr;
SphericalHarmonicsGravityModel* _sph_ptr = nullptr;
MSISAtmosphereModel* _msis_ptr = nullptr;
// Internal signals for the mapping of planet values to spacecraft
SIGNAL(_mu, double, warpos::earth_wgs84.mu);
SIGNAL(_eq_radius, double, warpos::earth_wgs84.eq_radius);
SIGNAL(_flattening, double, warpos::earth_wgs84.flattening);
SIGNAL(_J2, double, warpos::earth_wgs84.J2);
SIGNAL(_J3, double, warpos::earth_wgs84.J3);
std::string _planet_name = "earth";
// Vector of programmed burn models
std::vector<TimedImpulsiveBurnModel*> _planned_burn_ptrs;
// Vector of power loads from components (Watts)
std::vector<clockwerk::DataIO<double>*> _power_load_ptrs;
// Vector of power sources from components (Watts)
std::vector<clockwerk::DataIO<double>*> _power_source_ptrs;
};
}
#endif