LCOV - code coverage report
Current view: top level - SITL - SIM_Aircraft.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 46 48 95.8 %
Date: 2026-09-09 11:02:08 Functions: 28 29 96.6 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : /*
      16             :   parent class for aircraft simulators
      17             : */
      18             : 
      19             : #pragma once
      20             : 
      21             : #if AP_SIM_ENABLED
      22             : 
      23             : #include <AP_Math/AP_Math.h>
      24             : 
      25             : #include "SITL.h"
      26             : #include "SITL_Input.h"
      27             : #include "SIM_RichenPower.h"
      28             : #include "SIM_Loweheiser.h"
      29             : #include "SIM_FETtecOneWireESC.h"
      30             : #include "SIM_Volz.h"
      31             : #include "SIM_I2C.h"
      32             : #include "SIM_Battery.h"
      33             : #include <Filter/Filter.h>
      34             : #include "SIM_JSON_Master.h"
      35             : #include "ServoModel.h"
      36             : #include "SIM_GPIO_LED_1.h"
      37             : #include "SIM_GPIO_LED_2.h"
      38             : #include "SIM_GPIO_LED_3.h"
      39             : #include "SIM_GPIO_LED_RGB.h"
      40             : #include "SIM_Siyi.h"
      41             : #include "SIM_Topotek.h"
      42             : #include "SIM_Viewpro.h"
      43             : #include "SIM_Mount.h"
      44             : 
      45             : #define MAX_SIM_INSTANCES 16
      46             : 
      47             : namespace SITL {
      48             : 
      49             : /*
      50             :   parent class for all simulator types
      51             :  */
      52             : class Aircraft {
      53             : public:
      54             :     Aircraft(const char *frame_str);
      55             : 
      56             :     // called directly after constructor:
      57             :     virtual void set_start_location(const Location &start_loc, const float start_yaw);
      58             : 
      59             :     /*
      60             :       set simulation speedup
      61             :      */
      62             :     void set_speedup(float speedup);
      63   148005893 :     float get_speedup() const { return target_speedup; }
      64             : 
      65             :     /*
      66             :       set instance number
      67             :      */
      68        2094 :     void set_instance(uint8_t _instance) {
      69        2094 :         instance = _instance;
      70             :         // register at 0 whatever our instance number is: there is only
      71             :         // ever one Aircraft in a SITL process, and _instance is the -I
      72             :         // number, which separates the ports and directories of separate
      73             :         // processes rather than indexing aircraft within one.  Indexing
      74             :         // by it left instances[0] empty for every -I but zero, so
      75             :         // scripts calling sim:set_pose(0, ...) - as the shipped
      76             :         // sim_arming_pos.lua example does - silently did nothing.
      77        2094 :         instances[0] = this;
      78        2094 :     }
      79             : 
      80             :     /*
      81             :       set directory for additional files such as aircraft models
      82             :      */
      83        2094 :     void set_autotest_dir(const char *_autotest_dir) {
      84        2094 :         autotest_dir = _autotest_dir;
      85        2094 :     }
      86             : 
      87             :     /*  Create and set in/out socket for extenal simulator */
      88        2094 :     virtual void set_interface_ports(const char* address, const int port_in, const int port_out) {};
      89             : 
      90             :     /*
      91             :       Start the external simulator process, for backends that manage one. Called
      92             :       once the model is fully configured, so the child's command line can depend
      93             :       on anything the setters above supply.
      94             :      */
      95        2094 :     virtual void launch_external_sim(void) {};
      96             : 
      97             :     /*
      98             :       step the FDM by one time step
      99             :      */
     100             :     virtual void update(const struct sitl_input &input) = 0;
     101             : 
     102             :     void update_model(const struct sitl_input &input);
     103             : 
     104             :     void update_home();
     105             : 
     106             :     /* fill a sitl_fdm structure from the simulator state */
     107             :     void fill_fdm(struct sitl_fdm &fdm);
     108             : 
     109             :     /* smooth sensors to provide kinematic consistancy */
     110             :     void smooth_sensors(void);
     111             : 
     112             :     /* return normal distribution random numbers */
     113             :     static double rand_normal(double mean, double stddev);
     114             : 
     115             :     // get frame rate of model in Hz
     116             :     float get_rate_hz(void) const { return rate_hz; }
     117             : 
     118   108505077 :     const Vector3f &get_gyro(void) const {
     119   108505077 :         return gyro;
     120             :     }
     121             : 
     122    42572386 :     const Vector3f &get_velocity_ef(void) const {
     123    42572386 :         return velocity_ef;
     124             :     }
     125             : 
     126             :     // return TAS airspeed in earth frame
     127   107945231 :     const Vector3f &get_velocity_air_ef(void) const {
     128   107945231 :         return velocity_air_ef;
     129             :     }
     130             : 
     131   109876522 :     const Matrix3f &get_dcm(void) const {
     132   109876522 :         return dcm;
     133             :     }
     134             : 
     135             :     const Vector3f &get_mag_field_bf(void) const {
     136             :         return mag_bf;
     137             :     }
     138             : 
     139   107945231 :     float gross_mass() const { return mass + external_payload_mass; }
     140             : 
     141        2094 :     virtual void set_config(const char* config) {
     142        2094 :         config_ = config;
     143        2094 :     }
     144             : 
     145             :     // return simulation origin:
     146       80556 :     const Location &get_origin() const { return origin; }
     147             : 
     148   110163645 :     const Location &get_location() const { return location; }
     149             : 
     150             :     // get position relative to home
     151             :     Vector3d get_position_relhome() const;
     152             : 
     153             :     // get air density in kg/m^3
     154             :     float get_air_density(float alt_amsl) const;
     155             : 
     156             :     // distance the rangefinder is perceiving
     157             :     float rangefinder_range() const;
     158             : 
     159   179646075 :     void get_attitude(Quaternion &attitude) const {
     160   179646075 :         attitude.from_rotation_matrix(dcm);
     161   179646075 :     }
     162             : 
     163        2094 :     const Location &get_home() const { return home; }
     164        2094 :     float get_home_yaw() const { return home_yaw; }
     165             : 
     166           1 :     void set_richenpower(RichenPower *_richenpower) { richenpower = _richenpower; }
     167           7 :     void set_adsb(class ADSB *_adsb) { adsb = _adsb; }
     168             : #if AP_SIM_LOWEHEISER_ENABLED
     169          10 :     void set_loweheiser(Loweheiser *_loweheiser) { loweheiser = _loweheiser; }
     170             : #endif
     171          16 :     void set_fetteconewireesc(FETtecOneWireESC *_fetteconewireesc) { fetteconewireesc = _fetteconewireesc; }
     172             : #if AP_SIM_VOLZ_ENABLED
     173           3 :     void set_volz(Volz *_volz) { volz = _volz; }
     174             : #endif
     175           4 :     void set_ie24(IntelligentEnergy24 *_ie24) { ie24 = _ie24; }
     176  1176889686 :     float get_battery_voltage() const { return battery_voltage; }
     177           0 :     float get_battery_temperature_degC() const { return battery_temperature_degC; }
     178   187275482 :     float get_battery_current() const { return battery_current; }
     179             : 
     180             :     float ambient_outside_temperature_degC() const;
     181             :     float ambient_outside_pressure_Pascal() const;
     182             :     float baro_temperature_degC() const;
     183             : 
     184             : #if AP_SIM_MOUNT_ENABLED
     185           9 :     void add_gimbal_sim(Mount &sim) {
     186          11 :         for (uint8_t i = 0; i < GIMBAL_SIM_MAX; i++) {
     187          11 :             if (gimbal_sims[i] == nullptr) {
     188           9 :                 gimbal_sims[i] = &sim;
     189           9 :                 return;
     190             :             }
     191             :         }
     192           0 :         AP_HAL::panic("Too many gimbal simulators");
     193             :     }
     194             : #endif  // AP_SIM_MOUNT_ENABLED
     195             : 
     196             :     ADSB *adsb;
     197             : 
     198             :     // takes a PWM range between 1000 and 2000 and returns a floating
     199             :     // point value between -1 and 1
     200    30540181 :     float normalise_servo_input(uint16_t input) const {
     201    30540181 :         return 2*((input-1000)/1000.0f - 0.5f);
     202             :     }
     203             : 
     204             :     ServoModel servo_filter[16];
     205             : 
     206     1728432 :     float get_airspeed_pitot() const { return airspeed_pitot; }
     207             : 
     208             :     /*
     209             :       used by scripting to control simulated aircraft position
     210             :      */
     211             :     static bool set_pose(uint8_t instance, const Location &loc, const Quaternion &quat,
     212             :                          const Vector3f &velocity_ef, const Vector3f &gyro_rads);
     213             : 
     214             : protected:
     215             :     SIM *sitl;
     216             :     // origin of position vector
     217             :     Location origin;
     218             :     // home location
     219             :     Location home;
     220             :     bool home_is_set;
     221             :     Location location;
     222             : 
     223             :     float ground_level;
     224             :     float home_yaw;
     225             :     float frame_height;
     226             :     Matrix3f dcm;                        // rotation matrix, APM conventions, from body to earth
     227             :     Vector3f gyro;                       // rad/s
     228             :     Vector3f velocity_ef;                // m/s, earth frame
     229             :     Vector3f wind_ef;                    // m/s, earth frame
     230             :     Vector3f velocity_air_ef;            // velocity relative to airmass, earth frame (true airspeed)
     231             :     Vector3f velocity_air_bf;            // velocity relative to airmass, body frame
     232             :     Vector3d position;                   // meters, NED from origin
     233             :     float mass;                          // kg
     234             :     float external_payload_mass;         // kg
     235             :     Vector3f accel_body{0.0f, 0.0f, -GRAVITY_MSS}; // m/s/s NED, body frame
     236             :     float airspeed;                      // m/s, EAS airspeed
     237             :     float airspeed_pitot;                // m/s, EAS airspeed, as seen by fwd pitot tube
     238             :     float battery_voltage;
     239             :     float battery_current;
     240             :     float battery_temperature_degC;
     241             :     float local_ground_level;            // ground level at local position
     242             :     bool lock_step_scheduled;
     243             :     bool flightaxis_sync_imus_to_frames; // causes the frame counter to be incremented on each timestep, IMUs will then update at the same rate
     244             :     uint32_t last_one_hz_ms;
     245             : 
     246             :     // OPTIONAL internal battery model.
     247             :     // ("OPTIONAL" because a child can ignore it and directly set battery_* protected members, exposed publicly via getters.)
     248             :     // (Note that some aircraft get battery-info from an external source, ignoring this "internal" one.)
     249             :     Battery battery;
     250             : 
     251             :     uint32_t motor_mask;
     252             :     float rpm[32];
     253             :     uint8_t rcin_chan_count;
     254             :     float rcin[12];
     255             : 
     256  2049944438 :     virtual float rangefinder_beam_width() const { return 0; }
     257             :     virtual float perpendicular_distance_to_rangefinder_surface() const;
     258             : 
     259             :     struct {
     260             :         // data from simulated laser scanner, if available
     261             :         struct vector3f_array points;
     262             :         struct float_array ranges;
     263             :     } scanner;
     264             : 
     265             :     // Rangefinder
     266             :     float rangefinder_m[SITL_NUM_RANGEFINDERS];
     267             : 
     268             :     // Windvane apparent wind
     269             :     struct {
     270             :         float speed;
     271             :         float direction;
     272             :     } wind_vane_apparent;
     273             : 
     274             :     // Wind Turbulence simulated Data
     275             :     float turbulence_azimuth;
     276             :     float turbulence_horizontal_speed;  // m/s
     277             :     float turbulence_vertical_speed;    // m/s
     278             : 
     279             :     Vector3f mag_bf;  // local earth magnetic field vector in Gauss, earth frame
     280             : 
     281             :     uint64_t time_now_us;
     282             : 
     283             :     const float gyro_noise = radians(0.1f);
     284             :     const float accel_noise = 0.3f;
     285             :     float rate_hz = 1200.0f;
     286             :     float target_speedup;
     287             :     uint64_t frame_time_us;
     288             :     uint64_t last_wall_time_us;
     289             :     uint32_t last_fps_report_ms;
     290             :     float achieved_rate_hz;  // achieved speedup rate
     291             :     int64_t sleep_debt_us;
     292             :     uint32_t last_frame_count;
     293             :     uint8_t instance;
     294             :     const char *autotest_dir;
     295             :     bool use_time_sync = true;
     296             :     float last_speedup = -1.0f;
     297             :     const char *config_ = "";
     298             :     float eas2tas = 1.0;
     299             :     float air_density = SSL_AIR_DENSITY;
     300             : 
     301             :     // allow for AHRS_ORIENTATION
     302             :     AP_Int8 *ahrs_orientation;
     303             :     enum Rotation last_imu_rotation;
     304             :     AP_Float* custom_roll;
     305             :     AP_Float* custom_pitch;
     306             :     AP_Float* custom_yaw;
     307             : 
     308             :     enum GroundBehaviour {
     309             :         GROUND_BEHAVIOR_NONE = 0,
     310             :         GROUND_BEHAVIOR_NO_MOVEMENT,
     311             :         GROUND_BEHAVIOR_FWD_ONLY,
     312             :         GROUND_BEHAVIOR_TAILSITTER,
     313             :     } ground_behavior;
     314             : 
     315             :     bool use_smoothing;
     316             :     bool disable_origin_movement;
     317             : 
     318             :     float ground_height_difference() const;
     319             : 
     320             :     virtual bool on_ground() const;
     321             : 
     322             :     // returns height above ground level in metres
     323             :     float hagl() const;  // metres
     324             : 
     325             :     /* update location from position */
     326             :     void update_position(void);
     327             : 
     328             :     /* update body frame magnetic field */
     329             :     void update_mag_field_bf(void);
     330             : 
     331             :     /* advance time by deltat in seconds */
     332             :     void time_advance();
     333             : 
     334             :     /* setup the frame step time */
     335             :     void setup_frame_time(float rate, float speedup);
     336             : 
     337             :     /* adjust frame_time calculation */
     338             :     void adjust_frame_time(float rate);
     339             : 
     340             :     /* try to synchronise simulation time with wall clock time, taking
     341             :        into account desired speedup */
     342             :     void sync_frame_time(void);
     343             : 
     344             :     /* add noise based on throttle level (from 0..1) */
     345             :     void add_noise(float throttle);
     346             : 
     347             :     /* return a monotonic wall clock time in microseconds */
     348             :     uint64_t get_wall_time_us(void) const;
     349             : 
     350             :     // update attitude and relative position
     351             :     void update_dynamics(const Vector3f &rot_accel);
     352             : 
     353             :     // update wind vector
     354             :     void update_wind(const struct sitl_input &input);
     355             : 
     356             :     // return filtered servo input as -1 to 1 range
     357             :     float filtered_servo_angle(const struct sitl_input &input, uint8_t idx);
     358             :     float filtered_servo_range(const struct sitl_input &input, uint8_t idx);
     359             :     void filtered_servo_setup(uint8_t idx, uint16_t pwm_min, uint16_t pwm_max, float deflection_deg);
     360             : 
     361             :     // extrapolate sensors by a given delta time in seconds
     362             :     void extrapolate_sensors(float delta_time);
     363             : 
     364             :     // update battery
     365             :     virtual void update_battery();
     366             :     virtual void update_battery(const struct sitl_input &input);
     367             : 
     368             :     // update external payload/sensor dynamic
     369             :     void update_external_payload(const struct sitl_input &input);
     370             : 
     371             :     void add_shove_forces(Vector3f &rot_accel, Vector3f &body_accel);
     372             :     void add_twist_forces(Vector3f &rot_accel);
     373             : 
     374             :     // add body-frame force due to payload
     375             :     void add_external_forces(Vector3f &body_accel);
     376             : 
     377             :     // get local thermal updraft
     378             :     float get_local_updraft(const Vector3d &currentPos);
     379             : 
     380             :     // update EAS speeds
     381             :     void update_eas_airspeed();
     382             : 
     383             :     // clamp support
     384             :     class Clamp {
     385             :     public:
     386             :         bool clamped(class Aircraft&, const struct sitl_input &input);  // true if the vehicle is currently clamped down
     387             :     private:
     388             :         bool currently_clamped;
     389             :         bool grab_attempted;  // avoid warning multiple times about missed grab
     390             :     } clamp;
     391             : 
     392             : private:
     393             :     uint64_t last_time_us;
     394             :     uint32_t frame_counter;
     395             :     uint32_t last_ground_contact_ms;
     396             : #if defined(__CYGWIN__) || defined(__CYGWIN64__)
     397             :     const uint32_t min_sleep_time{20000};
     398             : #else
     399             :     const uint32_t min_sleep_time{5000};
     400             : #endif
     401             : 
     402             :     struct {
     403             :         Vector3f accel_body;
     404             :         Vector3f gyro;
     405             :         Matrix3f rotation_b2e;
     406             :         Vector3d position;
     407             :         Vector3f velocity_ef;
     408             :         uint64_t last_update_us;
     409             :         Location location;
     410             :     } smoothing;
     411             : 
     412             :     RichenPower *richenpower;
     413             : #if AP_SIM_LOWEHEISER_ENABLED
     414             :     Loweheiser *loweheiser;
     415             : #endif
     416             :     FETtecOneWireESC *fetteconewireesc;
     417             : #if AP_SIM_VOLZ_ENABLED
     418             :     Volz *volz;
     419             : #endif  // AP_SIM_VOLZ_ENABLED
     420             : 
     421             :     IntelligentEnergy24 *ie24;
     422             : 
     423             : 
     424             : #if AP_SIM_GPIO_LED_1_ENABLED
     425             :     GPIO_LED_1 sim_led1{8};  // pin to match sitl.h
     426             : #endif
     427             : #if AP_SIM_GPIO_LED_2_ENABLED
     428             :     GPIO_LED_2 sim_led2{13, 14};  // pins to match sitl.h
     429             : #endif
     430             : #if AP_SIM_GPIO_LED_3_ENABLED
     431             :     GPIO_LED_3 sim_led3{13, 14, 15};  // pins to match sitl.h
     432             : #endif
     433             : #if AP_SIM_GPIO_LED_RGB_ENABLED
     434             :     GPIO_LED_RGB sim_ledrgb{8, 9, 10};  // pins to match sitl.h
     435             : #endif
     436             : 
     437             :     static Aircraft *instances[MAX_SIM_INSTANCES];
     438             :     HAL_Semaphore pose_sem;
     439             : 
     440             : #if AP_SIM_MOUNT_ENABLED
     441             :     static constexpr uint8_t GIMBAL_SIM_MAX = 8;
     442             :     Mount *gimbal_sims[GIMBAL_SIM_MAX];
     443             : #endif
     444             : };
     445             : 
     446             : } // namespace SITL
     447             : 
     448             : #endif // AP_SIM_ENABLED

Generated by: LCOV version 1.14