34 #pragma GCC diagnostic push
35 #pragma GCC diagnostic ignored "-Wunused-parameter"
37 #include <FGFDMExec.h>
38 #include <FGJSBBase.h>
39 #include <initialization/FGInitialCondition.h>
40 #include <models/FGPropulsion.h>
41 #include <models/FGGroundReactions.h>
42 #include <models/FGAccelerations.h>
43 #include <models/FGAuxiliary.h>
44 #include <models/FGAtmosphere.h>
45 #include <models/FGAircraft.h>
46 #include <models/FGFCS.h>
47 #include <models/atmosphere/FGWinds.h>
50 #include <models/propulsion/FGThruster.h>
51 #include <models/propulsion/FGPropeller.h>
54 #pragma GCC diagnostic pop
66 #include "generated/airframe.h"
67 #include "generated/flight_plan.h"
70 #define MetersOfFeet(_f) ((_f)/3.2808399)
71 #define FeetOfMeters(_m) ((_m)*3.2808399)
73 #define PascalOfPsf(_p) ((_p) * 47.8802588889)
74 #define CelsiusOfRankine(_r) (((_r) - 491.67) / 1.8)
77 #if NPS_JSBSIM_USE_SGPATH
78 #define JSBSIM_PATH(_x) SGPath(_x)
80 #define JSBSIM_PATH(_x) _x
84 #ifdef NPS_USE_COMMANDS
85 #define NPS_AUTOMATIC_JSBSIM_ACTUATOR_NAMES TRUE
88 #ifdef NPS_ACTUATOR_NAMES
89 #define NPS_AUTOMATIC_JSBSIM_ACTUATOR_NAMES TRUE
92 #ifndef NPS_AUTOMATIC_JSBSIM_ACTUATOR_NAMES
93 #define NPS_AUTOMATIC_JSBSIM_ACTUATOR_NAMES FALSE
99 #ifndef NPS_JSBSIM_MODEL
100 #define NPS_JSBSIM_MODEL AIRFRAME_NAME
103 #ifdef NPS_INITIAL_CONDITITONS
104 #warning NPS_INITIAL_CONDITITONS was replaced by NPS_JSBSIM_INIT!
105 #warning Defaulting to flight plan location.
111 #ifndef NPS_JSBSIM_PITCH_TRIM
112 #define NPS_JSBSIM_PITCH_TRIM 0.0
115 #ifndef NPS_JSBSIM_ROLL_TRIM
116 #define NPS_JSBSIM_ROLL_TRIM 0.0
119 #ifndef NPS_JSBSIM_YAW_TRIM
120 #define NPS_JSBSIM_YAW_TRIM 0.0
126 #define DEG2RAD 0.017
128 #ifndef NPS_JSBSIM_ELEVATOR_MAX_RAD
129 #define NPS_JSBSIM_ELEVATOR_MAX_RAD (20.0*DEG2RAD)
132 #ifndef NPS_JSBSIM_AILERON_MAX_RAD
133 #define NPS_JSBSIM_AILERON_MAX_RAD (20.0*DEG2RAD)
136 #ifndef NPS_JSBSIM_RUDDER_MAX_RAD
137 #define NPS_JSBSIM_RUDDER_MAX_RAD (20.0*DEG2RAD)
140 #ifndef NPS_JSBSIM_FLAP_MAX_RAD
141 #define NPS_JSBSIM_FLAP_MAX_RAD (20.0*DEG2RAD)
147 #define MIN_DT (1.0/10240.0)
151 using namespace JSBSim;
210 printf(
"fdm.time,fdm.body_ecef_accel.x,fdm.body_ecef_accel.y,fdm.body_ecef_accel.z,fdm.ltp_ecef_accel.x,fdm.ltp_ecef_accel.y,fdm.ltp_ecef_accel.z,fdm.ecef_ecef_accel.x,fdm.ecef_ecef_accel.y,fdm.ecef_ecef_accel.z,fdm.ltpprz_ecef_accel.z,fdm.ltpprz_ecef_accel.y,fdm.ltpprz_ecef_accel.z,fdm.agl\n");
220 #ifdef NPS_JSBSIM_LAUNCHSPEED
221 static bool already_launched =
FALSE;
223 if (launch && !already_launched) {
224 printf(
"Launching with speed of %.1f m/s!\n", (
float)NPS_JSBSIM_LAUNCHSPEED);
227 already_launched =
TRUE;
254 if (numDT_to_impact <= 1.0) {
269 for (i = 0; i < num_steps; i++) {
277 printf(
"Error: FDM simulation encountered a total of %i NaN values at simulation time %f.\n",
fdm.
nan_count,
fdm.
time);
278 printf(
"It is likely the simulation diverged and gave non-physical results. If you did\n");
279 printf(
"not crash, check your model and/or initial conditions. Exiting with status 1.\n");
287 FGWinds *Winds =
FDMExec->GetWinds();
289 Winds->SetWindPsi(
dir);
294 FGWinds *Winds =
FDMExec->GetWinds();
301 FGWinds *Winds =
FDMExec->GetWinds();
304 Winds->SetProbabilityOfExceedence(turbulence_severity);
309 FDMExec->GetAtmosphere()->SetTemperature(temp,
h, FGAtmosphere::eCelsius);
320 #if NPS_AUTOMATIC_JSBSIM_ACTUATOR_NAMES
322 #if defined(NPS_USE_COMMANDS)
323 const char *names[] = COMMAND_NAMES;
324 #elif defined(NPS_ACTUATOR_NAMES)
325 const char *names[] = NPS_ACTUATOR_NAMES;
329 for (i = 0; i < commands_nb; i++) {
330 sprintf(buf,
"fcs/%s", names[i]);
331 property = string(buf);
332 FDMExec->GetPropertyManager()->GetNode(property)->SetDouble(
"",
commands[i]);
336 FGFCS *FCS =
FDMExec->GetFCS();
343 #ifdef COMMAND_THROTTLE
344 FGPropulsion *FProp =
FDMExec->GetPropulsion();
345 for (
unsigned int i = 0; i <
FDMExec->GetPropulsion()->GetNumEngines(); i++) {
346 FCS->SetThrottleCmd(i,
commands[COMMAND_THROTTLE]);
349 if (
commands[COMMAND_THROTTLE] > 0.01) {
350 FProp->SetStarter(1);
352 FProp->SetStarter(0);
358 FCS->SetDaCmd(
commands[COMMAND_ROLL]);
362 FCS->SetDeCmd(
commands[COMMAND_PITCH]);
366 FCS->SetDrCmd(
commands[COMMAND_YAW]);
370 FCS->SetDfCmd(
commands[COMMAND_FLAP]);
382 fdm.
time =
FDMExec->GetPropertyManager()->GetNode(
"simulation/sim-time-sec")->getDoubleValue();
388 FGPropagate *propagate =
FDMExec->GetPropagate();
389 FGAccelerations *accelerations =
FDMExec->GetAccelerations();
397 fdm.
hmsl = propagate->GetAltitudeASLmeters();
415 const FGColumnVector3 &fg_ltp_ecef_accel = propagate->GetTb2l() * accelerations->GetUVWdot();
423 const FGColumnVector3 &fg_ecef_ecef_vel = propagate->GetECEFVelocity();
426 const FGColumnVector3 &fg_ecef_ecef_accel = propagate->GetTb2ec() * accelerations->GetUVWdot();
458 const FGQuaternion jsb_quat = propagate->GetQuaternion();
480 const FGColumnVector3 &fg_wind_ned =
FDMExec->GetWinds()->GetTotalWindNED();
496 fdm.
aoa=
FDMExec->GetPropertyManager()->GetNode(
"aero/alpha-rad")->getDoubleValue();
497 fdm.
sideslip =
FDMExec->GetPropertyManager()->GetNode(
"aero/beta-rad")->getDoubleValue();
503 fdm.
rudder = (
FDMExec->GetPropertyManager()->GetNode(
"fcs/rudder-pos-rad")->getDoubleValue()) /
505 fdm.
left_aileron = (-1 *
FDMExec->GetPropertyManager()->GetNode(
"fcs/left-aileron-pos-rad")->getDoubleValue()) /
509 fdm.
elevator = (
FDMExec->GetPropertyManager()->GetNode(
"fcs/elevator-pos-rad")->getDoubleValue()) /
516 FGPropulsion *FGProp =
FDMExec->GetPropulsion();
525 FGEngine *FGEng = FGProp->GetEngine(k);
526 FGThruster *FGThrst = FGEng->GetThruster();
528 fdm.
rpm[k] = (float) FGThrst->GetRPM();
549 string jsbsim_home =
"/conf/simulator/jsbsim/";
550 string jsbsim_ic_name;
552 char* pprz_home = getenv(
"PAPARAZZI_HOME");
555 if (strlen(pprz_home) <
sizeof(buf)) {
556 cnt = snprintf(buf, strlen(pprz_home) + 1,
"%s", pprz_home);
557 rootdir = string(buf) + jsbsim_home;
564 cout <<
"PPRZ_HOME not set correctly, exiting..." << endl;
571 #ifdef NPS_JSBSIM_INIT
572 jsbsim_ic_name = NPS_JSBSIM_INIT;
589 cerr <<
" JSBSim could not be started" << endl << endl;
597 cerr <<
"NumEngines: " <<
FDMExec->GetPropulsion()->GetNumEngines() << endl;
598 cerr <<
"NumGearUnits: " <<
FDMExec->GetGroundReactions()->GetNumGearUnits() << endl;
604 FGInitialCondition *IC =
FDMExec->GetIC();
605 if (!jsbsim_ic_name.empty()) {
608 cerr <<
"Initialization unsuccessful" << endl;
615 cout <<
"JSBSim initial conditions loaded from " << jsbsim_ic_name << endl;
620 IC->SetVgroundFpsIC(0.);
624 double gd_lat = RadOfDeg(NAV_LAT0 / 1e7);
626 IC->SetLatitudeDegIC(DegOfRad(gc_lat));
627 IC->SetLongitudeDegIC(NAV_LON0 / 1e7);
629 IC->SetWindNEDFpsIC(0.0, 0.0, 0.0);
632 IC->SetPsiDegIC(QFU);
633 IC->SetVgroundFpsIC(0.);
635 lla0.
lon = RadOfDeg(NAV_LON0 / 1e7);
637 lla0.
alt = (double)(NAV_ALT0 + NAV_MSL0) / 1000.0;
646 cerr <<
"Initialization unsuccessful" << endl;
651 FDMExec->GetPropulsion()->InitRunning(-1);
665 int num_gear =
FDMExec->GetGroundReactions()->GetNumGearUnits();
667 for (i = 0; i < num_gear; i++) {
668 FGColumnVector3 gear_location =
FDMExec->GetGroundReactions()->GetGearUnit(i)->GetBodyLocation();
669 double radius =
MetersOfFeet(gear_location.Magnitude());
682 FGPropagate *propagate =
FDMExec->GetPropagate();
692 #if !NPS_CALC_GEO_MAG && defined(AHRS_H_X)
693 PRINT_CONFIG_MSG(
"Using magnetic field as defined in airframe file (AHRS section).")
697 #elif !NPS_CALC_GEO_MAG && defined(INS_H_X)
698 PRINT_CONFIG_MSG(
"Using magnetic field as defined in airframe file (INS section).")
703 PRINT_CONFIG_MSG(
"Using WMM2010 model to calculate magnetic field at simulated location.")
709 double sdate = 2019.0;
720 mag_calc(1, latitude, longitude, alt, nmax, gha,
773 fdm_quat->
qi = jsb_quat->Entry(1);
774 fdm_quat->
qx = jsb_quat->Entry(2);
775 fdm_quat->
qy = jsb_quat->Entry(3);
776 fdm_quat->
qz = jsb_quat->Entry(4);
789 fdm_rate->
p = jsb_vector->Entry(1);
790 fdm_rate->
q = jsb_vector->Entry(2);
791 fdm_rate->
r = jsb_vector->Entry(3);
806 fdm_lla->
lat = propagate->GetGeodLatitudeRad();
807 fdm_lla->
lon = propagate->GetLongitude();
808 fdm_lla->
alt = propagate->GetAltitudeASLmeters();
826 fdm_lla->
lat = propagate->GetLatitude();
827 fdm_lla->
lon = propagate->GetLongitude();
843 fdm_lla->
lat = propagate->GetGeodLatitudeRad();
844 fdm_lla->
lon = propagate->GetLongitude();
852 static int isnan(
double f) {
return (
f !=
f); }
static void h(const real32_T x[7], const real32_T q[4], real32_T y[6])
pprz_t commands[COMMANDS_NB]
void double_eulers_of_quat(struct DoubleEulers *e, struct DoubleQuat *q)
static void double_vect3_normalize(struct DoubleVect3 *v)
normalize 3D vector in place
#define EULERS_COPY(_a, _b)
#define VECT3_ASSIGN(_a, _x, _y, _z)
#define QUAT_COPY(_qo, _qi)
#define VECT3_DIFF(_c, _a, _b)
#define VECT3_ADD(_a, _b)
double alt
in meters above WGS84 reference ellipsoid
double gc_of_gd_lat_d(double gd_lat, double hmsl)
void ltp_def_from_ecef_d(struct LtpDef_d *def, struct EcefCoor_d *ecef)
void ned_of_ecef_vect_d(struct NedCoor_d *ned, struct LtpDef_d *def, struct EcefCoor_d *ecef)
void lla_of_ecef_d(struct LlaCoor_d *lla, struct EcefCoor_d *ecef)
void ned_of_ecef_point_d(struct NedCoor_d *ned, struct LtpDef_d *def, struct EcefCoor_d *ecef)
void ecef_of_lla_d(struct EcefCoor_d *ecef, struct LlaCoor_d *lla)
vector in EarthCenteredEarthFixed coordinates
vector in Latitude, Longitude and Altitude
definition of the local (flat earth) coordinate system
int16_t mag_calc(int16_t igdgc, double flat, double flon, double elev, int16_t nmax, double *gh, double *geo_mag_x, double *geo_mag_y, double *geo_mag_z, int16_t iext, double ext1, double ext2, double ext3)
int16_t extrapsh(double date, double dte1, int16_t nmax1, int16_t nmax2, double *gh)
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define NPS_COMMANDS_NB
Number of commands sent to the FDM of NPS.
double aoa
angle of attack in rad
struct NedCoor_d ltpprz_ecef_vel
velocity in ltppprz frame, wrt ECEF frame
double pressure_sl
pressure at sea level in Pascal
struct DoubleQuat ecef_to_body_quat
struct DoubleQuat ltpprz_to_body_quat
double total_pressure
total atmospheric pressure in Pascal
struct EcefCoor_d ecef_pos
struct NedCoor_d ltpprz_pos
struct LlaCoor_d lla_pos_pprz
struct DoubleVect3 body_inertial_accel
acceleration in body frame, wrt ECI inertial frame
struct DoubleRates body_inertial_rotvel
double airspeed
equivalent airspeed in m/s
struct NedCoor_d ltp_ecef_vel
velocity in LTP frame, wrt ECEF frame
struct NedCoor_d ltpprz_ecef_accel
accel in ltppprz frame, wrt ECEF frame
struct DoubleVect3 body_ecef_vel
velocity in body frame, wrt ECEF frame
double dynamic_pressure
dynamic pressure in Pascal
struct DoubleEulers ltp_to_body_eulers
struct EcefCoor_d ecef_ecef_accel
acceleration in ECEF frame, wrt ECEF frame
double pressure
current (static) atmospheric pressure in Pascal
struct DoubleQuat ltp_to_body_quat
struct DoubleRates body_ecef_rotvel
struct EcefCoor_d ecef_ecef_vel
velocity in ECEF frame, wrt ECEF frame
struct DoubleVect3 body_ecef_accel
acceleration in body frame, wrt ECEF frame
struct DoubleRates body_inertial_rotaccel
double temperature
current temperature in degrees Celcius
struct DoubleRates body_ecef_rotaccel
struct DoubleEulers ltpprz_to_body_eulers
float rpm[FG_NET_FDM_MAX_ENGINES]
uint32_t eng_state[FG_NET_FDM_MAX_ENGINES]
double sideslip
sideslip angle in rad
struct DoubleVect3 body_accel
acceleration in body frame as measured by an accelerometer (incl.
struct LlaCoor_d lla_pos_geoc
struct DoubleVect3 wind
velocity in m/s in NED
struct LlaCoor_d lla_pos_geod
struct NedCoor_d ltp_ecef_accel
acceleration in LTP frame, wrt ECEF frame
#define CelsiusOfRankine(_r)
void nps_fdm_set_wind_ned(double wind_north, double wind_east, double wind_down)
#define NPS_JSBSIM_RUDDER_MAX_RAD
double vehicle_radius_max
The largest distance between vehicle CG and contact point.
#define NPS_JSBSIM_PITCH_TRIM
Trim values for the airframe.
#define NPS_JSBSIM_MODEL
Name of the JSBSim model.
static FGFDMExec * FDMExec
The JSBSim executive object.
void nps_fdm_init(double dt)
NPS FDM rover init.
static void init_jsbsim(double dt)
Initializes JSBSim.
static void fetch_state(void)
Populates the NPS fdm struct after a simulation step.
static void lla_from_jsbsim_geodetic(LlaCoor_d *fdm_lla, FGPropagate *propagate)
Convert JSBSim location to NPS LLA.
static void init_ltp(void)
Initialize the ltp from the JSBSim location.
#define MIN_DT
Minimum JSBSim timestep Around 1/10000 seems to be good for ground impacts.
void nps_fdm_run_step(bool launch, double *commands, int commands_nb)
Minimum complexity flight dynamic model In legacy Paparazzi simulator, was implemented in OCaml and c...
static void jsbsimloc_to_loc(EcefCoor_d *fdm_location, const FGLocation *jsb_location)
Convert JSBSim location format and struct to NPS location format and struct.
#define NPS_JSBSIM_ELEVATOR_MAX_RAD
#define NPS_JSBSIM_FLAP_MAX_RAD
void nps_fdm_set_temperature(double temp, double h)
Set temperature in degrees Celcius at given height h above MSL.
static void jsbsimquat_to_quat(DoubleQuat *fdm_quat, const FGQuaternion *jsb_quat)
Convert JSBSim quaternion struct to NPS quaternion struct.
static void lla_from_jsbsim_geocentric(LlaCoor_d *fdm_lla, FGPropagate *propagate)
Convert JSBSim location to NPS LLA.
#define NPS_JSBSIM_YAW_TRIM
static int check_for_nan(void)
Checks NpsFdm struct for NaNs.
#define JSBSIM_PATH(_x)
Macro to build file path according to the lib version.
void nps_fdm_set_turbulence(double wind_speed, int turbulence_severity)
static void feed_jsbsim(double *commands, int commands_nb)
Feed JSBSim with the latest actuator commands.
static void jsbsimvec_to_vec(DoubleVect3 *fdm_vector, const FGColumnVector3 *jsb_vector)
Convert JSBSim vector format and struct to NPS vector format and struct.
static void jsbsimvec_to_rate(DoubleRates *fdm_rate, const FGColumnVector3 *jsb_vector)
Convert JSBSim rates vector struct to NPS rates struct.
#define NPS_JSBSIM_AILERON_MAX_RAD
void nps_fdm_set_wind(double speed, double dir)
double min_dt
Timestep used for higher fidelity near the ground.
#define MetersOfFeet(_f)
Macro to convert from feet to metres.
struct NpsFdm fdm
Holds all necessary NPS FDM state information.
static void llh_from_jsbsim(LlaCoor_d *fdm_lla, FGPropagate *propagate)
Convert JSBSim location to NPS LLH.
static struct LtpDef_d ltpdef
static struct EcefCoor_d offset
#define NPS_JSBSIM_ROLL_TRIM
Paparazzi generic algebra macros.
Paparazzi floating point algebra.
Paparazzi generic macros for geodetic calculations.
Paparazzi double-precision floating point math for geodetic calculations.
Paparazzi floating point math for geodetic calculations.
WMM2020 Geomagnetic field model.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
uint16_t f
Camera baseline, in meters (i.e. horizontal distance between the two cameras of the stereo setup)