#pragma once #include <AP_HAL/AP_HAL_Boards.h> #if AP_SIM_ENABLED #include <AP_Math/AP_Math.h> #include <GCS_MAVLink/GCS_MAVLink.h> #include <AP_Baro/AP_Baro.h> #include <AP_Airspeed/AP_Airspeed.h> #include <AP_Common/Location.h> #include <AP_Compass/AP_Compass.h> #include <AP_InertialSensor/AP_InertialSensor.h> #include "SIM_Buzzer.h" #include "SIM_Gripper_EPM.h" #include "SIM_Gripper_Servo.h" #include "SIM_I2C.h" #include "SIM_SPI.h" #include "SIM_Parachute.h" #include "SIM_Precland.h" #include "SIM_Sprayer.h" #include "SIM_ToneAlarm.h" #include "SIM_EFI_MegaSquirt.h" #include "SIM_RichenPower.h" #include "SIM_FETtecOneWireESC.h" #include "SIM_IntelligentEnergy24.h" #include "SIM_Ship.h" #include "SIM_GPS.h" #include "SIM_DroneCANDevice.h" namespace SITL { enum class LedLayout { ROWS=0, LUMINOUSBEE=1, }; struct vector3f_array { uint16_t length; Vector3f *data; }; struct float_array { uint16_t length; float *data; }; struct sitl_fdm { // this is the structure passed between FDM models and the main SITL code uint64_t timestamp_us; Location home; double latitude, longitude; // degrees double altitude; // MSL double heading; // degrees double speedN, speedE, speedD; // m/s double xAccel, yAccel, zAccel; // m/s/s in body frame double rollRate, pitchRate, yawRate; // degrees/s in body frame double rollDeg, pitchDeg, yawDeg; // euler angles, degrees Quaternion quaternion; double airspeed; // m/s Vector3f velocity_air_bf; // velocity relative to airmass, body frame double battery_voltage; // Volts double battery_current; // Amps double battery_remaining; // Ah, if non-zero capacity uint8_t num_motors; uint32_t motor_mask; float rpm[32]; // RPM of all motors uint8_t rcin_chan_count; float rcin[12]; // RC input 0..1 double range; // rangefinder value Vector3f bodyMagField; // Truth XYZ magnetic field vector in body-frame. Includes motor interference. Units are milli-Gauss. Vector3f angAccel; // Angular acceleration in degrees/s/s about the XYZ body axes struct { // data from simulated laser scanner, if available struct vector3f_array points; struct float_array ranges; } scanner; #define SITL_NUM_RANGEFINDERS 10 float rangefinder_m[SITL_NUM_RANGEFINDERS]; float airspeed_raw_pressure[AIRSPEED_MAX_SENSORS]; struct { float speed; float direction; } wind_vane_apparent; bool is_lock_step_scheduled; // earthframe wind, from backends that know it Vector3f wind_ef; }; // number of rc output channels #define SITL_NUM_CHANNELS 32 class SIM { public: SIM() { AP_Param::setup_object_defaults(this, var_info); AP_Param::setup_object_defaults(this, var_info2); AP_Param::setup_object_defaults(this, var_info3); #if HAL_SIM_GPS_ENABLED AP_Param::setup_object_defaults(this, var_gps); #endif AP_Param::setup_object_defaults(this, var_mag); AP_Param::setup_object_defaults(this, var_ins); #ifdef SFML_JOYSTICK AP_Param::setup_object_defaults(this, var_sfml_joystick); #endif // SFML_JOYSTICK for (uint8_t i=0; i<BARO_MAX_INSTANCES; i++) { AP_Param::setup_object_defaults(&baro[i], baro[i].var_info); } for (uint8_t i=0; i<AIRSPEED_MAX_SENSORS; i++) { AP_Param::setup_object_defaults(&airspeed[i], airspeed[i].var_info); } // set compass offset for (uint8_t i = 0; i < HAL_COMPASS_MAX_SENSORS; i++) { mag_ofs[i].set(Vector3f(5, 13, -18)); } if (_singleton != nullptr) { AP_HAL::panic("Too many SITL instances"); } _singleton = this; } /* Do not allow copies */ CLASS_NO_COPY(SIM); static SIM *_singleton; static SIM *get_singleton() { return _singleton; } enum SITL_RCFail { SITL_RCFail_None = 0, SITL_RCFail_NoPulses = 1, SITL_RCFail_Throttle950 = 2, }; enum GPSHeading { GPS_HEADING_NONE = 0, GPS_HEADING_HDT = 1, GPS_HEADING_THS = 2, GPS_HEADING_KSXT = 3, }; struct sitl_fdm state; // throttle when motors are active float throttle; // height above ground float height_agl; static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info2[]; static const struct AP_Param::GroupInfo var_info3[]; #if HAL_SIM_GPS_ENABLED static const struct AP_Param::GroupInfo var_gps[]; #endif static const struct AP_Param::GroupInfo var_mag[]; static const struct AP_Param::GroupInfo var_ins[]; #ifdef SFML_JOYSTICK static const struct AP_Param::GroupInfo var_sfml_joystick[]; #endif //SFML_JOYSTICK // Board Orientation (and inverse) Matrix3f ahrs_rotation; Matrix3f ahrs_rotation_inv; AP_Float mag_noise; // in mag units (earth field is 818) AP_Vector3f mag_mot; // in mag units per amp AP_Vector3f mag_ofs[HAL_COMPASS_MAX_SENSORS]; // in mag units AP_Vector3f mag_diag[HAL_COMPASS_MAX_SENSORS]; // diagonal corrections AP_Vector3f mag_offdiag[HAL_COMPASS_MAX_SENSORS]; // off-diagonal corrections AP_Int8 mag_orient[HAL_COMPASS_MAX_SENSORS]; // external compass orientation AP_Int8 mag_fail[HAL_COMPASS_MAX_SENSORS]; // fail magnetometer, 1 for no data, 2 for freeze AP_Float servo_speed; // servo speed in seconds AP_Float sonar_glitch;// probability between 0-1 that any given sonar sample will read as max distance AP_Float sonar_noise; // in metres AP_Float sonar_scale; // meters per volt AP_Int8 sonar_rot; // from rotations enumeration AP_Float drift_speed; // degrees/second/minute AP_Float drift_time; // period in minutes AP_Float engine_mul; // engine multiplier AP_Int8 engine_fail; // engine servo to fail (0-7) AP_Float gps_noise[2]; // amplitude of the gps altitude error AP_Int16 gps_lock_time[2]; // delay in seconds before GPS gets lock AP_Int16 gps_alt_offset[2]; // gps alt error AP_Int8 gps_disable[2]; // disable simulated GPS AP_Int16 gps_delay_ms[2]; // delay in milliseconds AP_Int8 gps_type[2]; // see enum SITL::GPS::Type AP_Float gps_byteloss[2];// byte loss as a percent AP_Int8 gps_numsats[2]; // number of visible satellites AP_Vector3f gps_glitch[2]; // glitch offsets in lat, lon and altitude AP_Int8 gps_hertz[2]; // GPS update rate in Hz AP_Int8 gps_hdg_enabled[2]; // enable the output of a NMEA heading HDT sentence or UBLOX RELPOSNED AP_Float gps_drift_alt[2]; // altitude drift error AP_Vector3f gps_pos_offset[2]; // XYZ position of the GPS antenna phase centre relative to the body frame origin (m) AP_Float gps_accuracy[2]; AP_Vector3f gps_vel_err[2]; // Velocity error offsets in NED (x = N, y = E, z = D) // initial offset on GPS lat/lon, used to shift origin AP_Float gps_init_lat_ofs; AP_Float gps_init_lon_ofs; AP_Float gps_init_alt_ofs; // log number for GPS::update_file() AP_Int16 gps_log_num; AP_Float batt_voltage; // battery voltage base AP_Float batt_capacity_ah; // battery capacity in Ah AP_Int8 rc_fail; // fail RC input AP_Int8 rc_chancount; // channel count AP_Int8 float_exception; // enable floating point exception checks AP_Int32 can_servo_mask; // mask of servos/escs coming from CAN #if HAL_NUM_CAN_IFACES enum class CANTransport : uint8_t { MulticastUDP = 0, SocketCAN = 1 }; AP_Enum<CANTransport> can_transport[HAL_NUM_CAN_IFACES]; #endif AP_Int8 flow_enable; // enable simulated optflow AP_Int16 flow_rate; // optflow data rate (Hz) AP_Int8 flow_delay; // optflow data delay AP_Int8 terrain_enable; // enable using terrain for height AP_Int16 pin_mask; // for GPIO emulation AP_Float speedup; // simulation speedup AP_Int8 odom_enable; // enable visual odometry data AP_Int8 telem_baudlimit_enable; // enable baudrate limiting on links AP_Float flow_noise; // optical flow measurement noise (rad/sec) AP_Int8 baro_count; // number of simulated baros to create AP_Int8 imu_count; // number of simulated IMUs to create AP_Int32 loop_delay; // extra delay to add to every loop AP_Float mag_scaling[MAX_CONNECTED_MAGS]; // scaling factor AP_Int32 mag_devid[MAX_CONNECTED_MAGS]; // Mag devid AP_Float buoyancy; // submarine buoyancy in Newtons AP_Int16 loop_rate_hz; AP_Int16 loop_time_jitter_us; AP_Int32 on_hardware_output_enable_mask; // mask of output channels passed through to actual hardware AP_Int16 on_hardware_relay_enable_mask; // mask of relays passed through to actual hardware AP_Float uart_byte_loss_pct; #ifdef SFML_JOYSTICK AP_Int8 sfml_joystick_id; AP_Int8 sfml_joystick_axis[8]; #endif // baro parameters class BaroParm { public: static const struct AP_Param::GroupInfo var_info[]; AP_Float noise; // in metres AP_Float drift; // in metres per second AP_Float glitch; // glitch in meters AP_Int8 freeze; // freeze baro to last recorded altitude AP_Int8 disable; // disable simulated barometers AP_Int16 delay; // barometer data delay in ms // wind coefficients AP_Float wcof_xp; AP_Float wcof_xn; AP_Float wcof_yp; AP_Float wcof_yn; AP_Float wcof_zp; AP_Float wcof_zn; }; BaroParm baro[BARO_MAX_INSTANCES]; // airspeed parameters class AirspeedParm { public: static const struct AP_Param::GroupInfo var_info[]; AP_Float noise; // pressure noise AP_Float fail; // airspeed value in m/s to fail to AP_Float fail_pressure; // pitot tube failure pressure in Pa AP_Float fail_pitot_pressure; // pitot tube failure pressure in Pa AP_Float offset; // airspeed sensor offset in m/s AP_Float ratio; // airspeed ratios AP_Int8 signflip; }; AirspeedParm airspeed[AIRSPEED_MAX_SENSORS]; // EFI type enum EFIType { EFI_TYPE_NONE = 0, EFI_TYPE_MS = 1, }; AP_Int8 efi_type; // wind control enum WindType { WIND_TYPE_SQRT = 0, WIND_TYPE_NO_LIMIT = 1, WIND_TYPE_COEF = 2, }; float wind_speed_active; float wind_direction_active; float wind_dir_z_active; AP_Float wind_speed; AP_Float wind_direction; AP_Float wind_turbulance; AP_Float wind_dir_z; AP_Int8 wind_type; // enum WindLimitType AP_Float wind_type_alt; AP_Float wind_type_coef; AP_Int16 mag_delay; // magnetometer data delay in ms // ADSB related run-time options AP_Int16 adsb_plane_count; AP_Float adsb_radius_m; AP_Float adsb_altitude_m; AP_Int8 adsb_tx; // Earth magnetic field anomaly AP_Vector3f mag_anomaly_ned; // NED anomaly vector at ground level (mGauss) AP_Float mag_anomaly_hgt; // height above ground where anomally strength has decayed to 1/8 of the ground level value (m) // Body frame sensor position offsets AP_Vector3f imu_pos_offset; // XYZ position of the IMU accelerometer relative to the body frame origin (m) AP_Vector3f rngfnd_pos_offset; // XYZ position of the range finder zero range datum relative to the body frame origin (m) AP_Vector3f optflow_pos_offset; // XYZ position of the optical flow sensor focal point relative to the body frame origin (m) AP_Vector3f vicon_pos_offset; // XYZ position of the vicon sensor relative to the body frame origin (m) // barometer temperature control AP_Float temp_start; // [deg C] Barometer start temperature AP_Float temp_board_offset; // [deg C] Barometer board temperature offset from atmospheric temperature AP_Float temp_tconst; // [deg C] Barometer warmup temperature time constant AP_Float temp_baro_factor; AP_Int8 thermal_scenario; // weight on wheels pin AP_Int8 wow_pin; // vibration frequencies in Hz on each axis AP_Vector3f vibe_freq; // max frequency to use as baseline for adding motor noise for the gyros and accels AP_Float vibe_motor; // amplitude scaling of motor noise relative to gyro/accel noise AP_Float vibe_motor_scale; // what harmonics to generate AP_Int16 vibe_motor_harmonics; // what servos are motors AP_Int32 vibe_motor_mask; // minimum throttle for addition of ins noise AP_Float ins_noise_throttle_min; struct { AP_Float x; AP_Float y; AP_Float z; AP_Int32 t; uint32_t start_ms; } shove; struct { AP_Float x; AP_Float y; AP_Float z; AP_Int32 t; uint32_t start_ms; } twist; AP_Int8 gnd_behav; struct { AP_Int8 enable; // 0: disabled, 1: roll and pitch, 2: roll, pitch and heave AP_Float length; // m AP_Float amp; // m AP_Float direction; // deg (direction wave is coming from) AP_Float speed; // m/s } wave; struct { AP_Float direction; // deg (direction tide is coming from) AP_Float speed; // m/s } tide; // original simulated position struct { AP_Float lat; AP_Float lng; AP_Float alt; // metres AP_Float hdg; // 0 to 360 } opos; uint16_t irlock_port; time_t start_time_UTC; void simstate_send(mavlink_channel_t chan) const; void sim_state_send(mavlink_channel_t chan) const; void Log_Write_SIMSTATE(); // convert a set of roll rates from earth frame to body frame static void convert_body_frame(double rollDeg, double pitchDeg, double rollRate, double pitchRate, double yawRate, double *p, double *q, double *r); // convert a set of roll rates from body frame to earth frame static Vector3f convert_earth_frame(const Matrix3f &dcm, const Vector3f &gyro); int i2c_ioctl(uint8_t i2c_operation, void *data) { return i2c_sim.ioctl(i2c_operation, data); } int spi_ioctl(uint8_t bus, uint8_t cs_pin, uint8_t spi_operation, void *data) { return spi_sim.ioctl(bus, cs_pin, spi_operation, data); } Sprayer sprayer_sim; // simulated ship takeoffs #if AP_SIM_SHIP_ENABLED ShipSim shipsim; #endif Gripper_Servo gripper_sim; Gripper_EPM gripper_epm_sim; Parachute parachute_sim; Buzzer buzzer_sim; I2C i2c_sim; SPI spi_sim; ToneAlarm tonealarm_sim; SIM_Precland precland_sim; RichenPower richenpower_sim; IntelligentEnergy24 ie24_sim; FETtecOneWireESC fetteconewireesc_sim; #if AP_TEST_DRONECAN_DRIVERS DroneCANDevice dronecan_sim; #endif // ESC telemetry AP_Int8 esc_telem; // RPM when motors are armed AP_Float esc_rpm_armed; struct { // LED state, for serial LED emulation struct { uint8_t rgb[3]; } rgb[16][32]; uint8_t num_leds[16]; uint32_t send_counter; } led; AP_Int8 led_layout; // vicon parameters AP_Vector3f vicon_glitch; // glitch in meters in vicon's local NED frame AP_Int8 vicon_fail; // trigger vicon failure AP_Int16 vicon_yaw; // vicon local yaw in degrees AP_Int16 vicon_yaw_error; // vicon yaw error in degrees (added to reported yaw sent to vehicle) AP_Int8 vicon_type_mask; // vicon message type mask (bit0:vision position estimate, bit1:vision speed estimate, bit2:vicon position estimate) AP_Vector3f vicon_vel_glitch; // velocity glitch in m/s in vicon's local frame // get the rangefinder reading for the desired instance, returns -1 for no data float get_rangefinder(uint8_t instance); float measure_distance_at_angle_bf(const Location &location, float angle) const; // get the apparent wind speed and direction as set by external physics backend float get_apparent_wind_dir() const{return state.wind_vane_apparent.direction;} float get_apparent_wind_spd() const{return state.wind_vane_apparent.speed;} #if HAL_INS_TEMPERATURE_CAL_ENABLE // IMU temperature calibration params AP_Float imu_temp_start; AP_Float imu_temp_end; AP_Float imu_temp_tconst; AP_Float imu_temp_fixed; AP_InertialSensor_TCal imu_tcal[INS_MAX_INSTANCES]; #endif // IMU control parameters AP_Float gyro_noise[INS_MAX_INSTANCES]; // in degrees/second AP_Vector3f gyro_scale[INS_MAX_INSTANCES]; // percentage AP_Vector3f gyro_bias[INS_MAX_INSTANCES]; // in rad/s AP_Float accel_noise[INS_MAX_INSTANCES]; // in m/s/s AP_Vector3f accel_bias[INS_MAX_INSTANCES]; // in m/s/s AP_Vector3f accel_scale[INS_MAX_INSTANCES]; // in m/s/s AP_Vector3f accel_trim; AP_Float accel_fail[INS_MAX_INSTANCES]; // accelerometer failure value // gyro and accel fail masks AP_Int8 gyro_fail_mask; AP_Int8 accel_fail_mask; // Sailboat sim only AP_Int8 sail_type; // Master instance to use servos from with slave instances AP_Int8 ride_along_master; #if AP_SIM_INS_FILE_ENABLED enum INSFileMode { INS_FILE_NONE = 0, INS_FILE_READ = 1, INS_FILE_WRITE = 2, INS_FILE_READ_STOP_ON_EOF = 3, }; AP_Int8 gyro_file_rw; AP_Int8 accel_file_rw; #endif }; } // namespace SITL namespace AP { SITL::SIM *sitl(); }; #endif // AP_SIM_ENABLED