/**************************************************************************** * * Copyright (c) 2025 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name PX4 nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace time_literals; class SensorSimManager : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem { public: SensorSimManager(); ~SensorSimManager() override; /** @see ModuleBase */ static int task_spawn(int argc, char *argv[]); /** @see ModuleBase */ static int custom_command(int argc, char *argv[]); /** @see ModuleBase */ static int print_usage(const char *reason = nullptr); bool init(); private: void Run() override; // Sensor simulation methods void updateGPS(); void updateBarometer(); void updateMagnetometer(); void updateAirspeed(); void updateAGP(); void updateIMU(); void updateDistanceSensor(); // Utility methods static float generate_wgn(); matrix::Vector3f noiseGauss3f(float stdx, float stdy, float stdz); // Sensor timing structure struct SensorTiming { hrt_abstime interval_us; hrt_abstime next_update_time; hrt_abstime offset_us; bool enabled; }; // Sensor timings with random offsets SensorTiming _gps_timing; SensorTiming _baro_timing; SensorTiming _mag_timing; SensorTiming _airspeed_timing; SensorTiming _agp_timing; SensorTiming _imu_timing; SensorTiming _distance_sensor_timing; SensorTiming _failure_update; // Subscriptions uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; uORB::Subscription _vehicle_global_position_sub{ORB_ID(vehicle_global_position_groundtruth)}; uORB::Subscription _vehicle_local_position_sub{ORB_ID(vehicle_local_position_groundtruth)}; uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude_groundtruth)}; uORB::Subscription _vehicle_angular_velocity_sub{ORB_ID(vehicle_angular_velocity_groundtruth)}; // Publications uORB::PublicationMulti _sensor_gps_pub{ORB_ID(sensor_gps)}; uORB::PublicationMulti _sensor_baro_pub{ORB_ID(sensor_baro)}; uORB::PublicationMulti _differential_pressure_pub{ORB_ID(differential_pressure)}; uORB::PublicationMulti _airspeed_pub{ORB_ID(airspeed)}; uORB::PublicationMulti _distance_sensor_pub{ORB_ID(distance_sensor)}; uORB::PublicationMulti _aux_global_position_pub{ORB_ID(aux_global_position)}; PX4Accelerometer _px4_accel{1310988, ROTATION_NONE}; // 1310988: DRV_IMU_DEVTYPE_SIM, BUS: 1, ADDR: 1, TYPE: SIMULATION PX4Gyroscope _px4_gyro{1310988, ROTATION_NONE}; // 1310988: DRV_IMU_DEVTYPE_SIM, BUS: 1, ADDR: 1, TYPE: SIMULATION PX4Magnetometer _px4_mag{197388, ROTATION_NONE}; // 197388: DRV_MAG_DEVTYPE_MAGSIM, BUS: 3, ADDR: 1, TYPE: SIMULATION FailureInjection _failure_injection{}; matrix::Vector3f _last_mag{}; float _last_baro_pressure{0.0f}; float _last_baro_temperature{0.0f}; perf_counter_t _loop_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")}; perf_counter_t _gps_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": gps")}; perf_counter_t _baro_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": baro")}; perf_counter_t _mag_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": mag")}; perf_counter_t _airspeed_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": airspeed")}; perf_counter_t _agp_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": agp")}; perf_counter_t _imu_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": imu")}; perf_counter_t _distance_sensor_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": distance")}; // Random number generator for offsets and noise std::random_device _rd; std::mt19937 _gen; std::uniform_real_distribution _uniform_dist; // Parameters DEFINE_PARAMETERS( (ParamInt) _param_sens_en_gpssim, (ParamInt) _param_sens_en_barosim, (ParamInt) _param_sens_en_magsim, (ParamInt) _param_sens_en_arspdsim, (ParamInt) _param_sens_en_agpsim, (ParamInt) _param_sens_en_distsim, (ParamInt) _sim_gps_used, (ParamFloat) _sim_baro_off_p, (ParamFloat) _sim_baro_off_t, (ParamFloat) _sim_mag_offset_x, (ParamFloat) _sim_mag_offset_y, (ParamFloat) _sim_mag_offset_z, (ParamFloat) _distance_snsr_min, (ParamFloat) _distance_snsr_max ) hrt_abstime _last_baro_update_time{0}; float _baro_drift_pa{0.0f}; float _baro_drift_pa_per_sec{0.1f}; bool _baro_rnd_use_last{false}; double _baro_rnd_y2{0.0}; matrix::Vector3f _mag_earth_pred{}; bool _mag_earth_available{false}; LatLonAlt _agp_measured_lla{}; matrix::Vector3f _agp_position_bias{}; uint64_t _agp_time_last_update{0}; matrix::Vector3f _last_accel{}; matrix::Vector3f _last_gyro{}; matrix::Vector3f _specific_force_E{}; float _last_distance_sensor_value{0.0f}; // Air constants static constexpr float TEMPERATURE_MSL = 288.0f; // [K] static constexpr float PRESSURE_MSL = 101325.0f; // [Pa] static constexpr float LAPSE_RATE = 0.0065f; // [K/m] static constexpr float AIR_DENSITY_MSL = 1.225f; // [kg/m^3] static constexpr float RHO = 1.225f; // Air density at sea level [kg/m^3] // IMU constants static constexpr float T1_C = 15.0f; // Temperature constant static constexpr hrt_abstime GROUNDTRUTH_DATA_MAX_AGE_US = 12000; // Parameter handles for cross-module access param_t _param_sim_gz_en_handle{PARAM_INVALID}; int32_t _sim_gz_en_value{0}; };