/**************************************************************************** * * Copyright (c) 2015 Mark Charlebois. All rights reserved. * Copyright (c) 2016-2019 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. * ****************************************************************************/ /** * @file simulator.h * * This module interfaces via MAVLink to a software in the loop simulator (SITL) * such as jMAVSim or Gazebo. */ #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 #include #include using namespace time_literals; //! Enumeration to use on the bitmask in HIL_SENSOR enum class SensorSource { ACCEL = 0b111, GYRO = 0b111000, MAG = 0b111000000, BARO = 0b1101000000000, DIFF_PRESS = 0b10000000000 }; ENABLE_BIT_OPERATORS(SensorSource) //! AND operation for the enumeration and unsigned types that returns the bitmask template static inline SensorSource operator &(A lhs, B rhs) { // make it type safe static_assert((std::is_same::value || std::is_same::value), "first argument is not uint32_t or SensorSource enum type"); static_assert((std::is_same::value || std::is_same::value), "second argument is not uint32_t or SensorSource enum type"); typedef typename std::underlying_type::type underlying; return static_cast( static_cast(lhs) & static_cast(rhs) ); } class Simulator : public ModuleParams { public: static Simulator *getInstance() { return _instance; } enum class InternetProtocol { TCP, UDP }; static int start(int argc, char *argv[]); void set_ip(InternetProtocol ip) { _ip = ip; } void set_port(unsigned port) { _port = port; } #if defined(ENABLE_LOCKSTEP_SCHEDULER) bool has_initialized() { return _has_initialized.load(); } #endif private: Simulator() : ModuleParams(nullptr) { } ~Simulator() { // free perf counters perf_free(_perf_sim_delay); perf_free(_perf_sim_interval); for (size_t i = 0; i < sizeof(_dist_pubs) / sizeof(_dist_pubs[0]); i++) { delete _dist_pubs[i]; } px4_lockstep_unregister_component(_lockstep_component); _instance = nullptr; } void check_failure_injections(); int publish_flow_topic(const mavlink_hil_optical_flow_t *flow); int publish_odometry_topic(const mavlink_message_t *odom_mavlink); int publish_distance_topic(const mavlink_distance_sensor_t *dist); static Simulator *_instance; // simulated sensor instances static constexpr uint8_t ACCEL_COUNT_MAX = 3; PX4Accelerometer _px4_accel[ACCEL_COUNT_MAX] { {1310988, ROTATION_NONE}, // 1310988: DRV_IMU_DEVTYPE_SIM, BUS: 1, ADDR: 1, TYPE: SIMULATION {1310996, ROTATION_NONE}, // 1310996: DRV_IMU_DEVTYPE_SIM, BUS: 2, ADDR: 1, TYPE: SIMULATION {1311004, ROTATION_NONE}, // 1311004: DRV_IMU_DEVTYPE_SIM, BUS: 3, ADDR: 1, TYPE: SIMULATION }; static constexpr uint8_t GYRO_COUNT_MAX = 3; PX4Gyroscope _px4_gyro[GYRO_COUNT_MAX] { {1310988, ROTATION_NONE}, // 1310988: DRV_IMU_DEVTYPE_SIM, BUS: 1, ADDR: 1, TYPE: SIMULATION {1310996, ROTATION_NONE}, // 1310996: DRV_IMU_DEVTYPE_SIM, BUS: 2, ADDR: 1, TYPE: SIMULATION {1311004, ROTATION_NONE}, // 1311004: DRV_IMU_DEVTYPE_SIM, BUS: 3, ADDR: 1, TYPE: SIMULATION }; PX4Magnetometer _px4_mag_0{197388, ROTATION_NONE}; // 197388: DRV_MAG_DEVTYPE_MAGSIM, BUS: 1, ADDR: 1, TYPE: SIMULATION PX4Magnetometer _px4_mag_1{197644, ROTATION_NONE}; // 197644: DRV_MAG_DEVTYPE_MAGSIM, BUS: 2, ADDR: 1, TYPE: SIMULATION PX4Barometer _px4_baro_0{6620172}; // 6620172: DRV_BARO_DEVTYPE_BAROSIM, BUS: 1, ADDR: 4, TYPE: SIMULATION PX4Barometer _px4_baro_1{6620428}; // 6620428: DRV_BARO_DEVTYPE_BAROSIM, BUS: 2, ADDR: 4, TYPE: SIMULATION float _sensors_temperature{0}; perf_counter_t _perf_sim_delay{perf_alloc(PC_ELAPSED, MODULE_NAME": network delay")}; perf_counter_t _perf_sim_interval{perf_alloc(PC_INTERVAL, MODULE_NAME": network interval")}; // uORB publisher handlers uORB::Publication _differential_pressure_pub{ORB_ID(differential_pressure)}; uORB::PublicationMulti _flow_pub{ORB_ID(optical_flow)}; uORB::Publication _irlock_report_pub{ORB_ID(irlock_report)}; uORB::Publication _visual_odometry_pub{ORB_ID(vehicle_visual_odometry)}; uORB::Publication _mocap_odometry_pub{ORB_ID(vehicle_mocap_odometry)}; uORB::Publication _command_ack_pub{ORB_ID(vehicle_command_ack)}; uORB::PublicationMulti *_dist_pubs[RANGE_FINDER_MAX_SENSORS] {}; uint8_t _dist_sensor_ids[RANGE_FINDER_MAX_SENSORS] {}; uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)}; unsigned int _port{14560}; InternetProtocol _ip{InternetProtocol::UDP}; double _realtime_factor{1.0}; ///< How fast the simulation runs in comparison to real system time hrt_abstime _last_sim_timestamp{0}; hrt_abstime _last_sitl_timestamp{0}; void run(); void handle_message(const mavlink_message_t *msg); void handle_message_distance_sensor(const mavlink_message_t *msg); void handle_message_hil_gps(const mavlink_message_t *msg); void handle_message_hil_sensor(const mavlink_message_t *msg); void handle_message_hil_state_quaternion(const mavlink_message_t *msg); void handle_message_landing_target(const mavlink_message_t *msg); void handle_message_odometry(const mavlink_message_t *msg); void handle_message_optical_flow(const mavlink_message_t *msg); void handle_message_rc_channels(const mavlink_message_t *msg); void handle_message_vision_position_estimate(const mavlink_message_t *msg); void parameters_update(bool force); void poll_for_MAVLink_messages(); void request_hil_state_quaternion(); void send(); void send_controls(); void send_heartbeat(); void send_mavlink_message(const mavlink_message_t &aMsg); void update_sensors(const hrt_abstime &time, const mavlink_hil_sensor_t &sensors); static void *sending_trampoline(void *); mavlink_hil_actuator_controls_t actuator_controls_from_outputs(); // uORB publisher handlers uORB::Publication _vehicle_angular_velocity_ground_truth_pub{ORB_ID(vehicle_angular_velocity_groundtruth)}; uORB::Publication _attitude_ground_truth_pub{ORB_ID(vehicle_attitude_groundtruth)}; uORB::Publication _gpos_ground_truth_pub{ORB_ID(vehicle_global_position_groundtruth)}; uORB::Publication _lpos_ground_truth_pub{ORB_ID(vehicle_local_position_groundtruth)}; uORB::Publication _input_rc_pub{ORB_ID(input_rc)}; // HIL GPS static constexpr int MAX_GPS = 3; uORB::PublicationMulti *_sensor_gps_pubs[MAX_GPS] {}; uint8_t _gps_ids[MAX_GPS] {}; std::default_random_engine _gen{}; // uORB subscription handlers int _actuator_outputs_sub{-1}; actuator_outputs_s _actuator_outputs{}; uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)}; uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)}; // hil map_ref data struct map_projection_reference_s _hil_local_proj_ref {}; bool _hil_local_proj_inited{false}; double _hil_ref_lat{0}; double _hil_ref_lon{0}; float _hil_ref_alt{0.0f}; uint64_t _hil_ref_timestamp{0}; vehicle_status_s _vehicle_status{}; bool _accel_blocked[ACCEL_COUNT_MAX] {}; bool _accel_stuck[ACCEL_COUNT_MAX] {}; matrix::Vector3f _last_accel[GYRO_COUNT_MAX] {}; bool _gyro_blocked[GYRO_COUNT_MAX] {}; bool _gyro_stuck[GYRO_COUNT_MAX] {}; matrix::Vector3f _last_gyro[GYRO_COUNT_MAX] {}; bool _baro_blocked{false}; bool _baro_stuck{false}; bool _mag_blocked{false}; bool _mag_stuck{false}; bool _gps_blocked{false}; bool _airspeed_blocked{false}; float _last_magx{0.0f}; float _last_magy{0.0f}; float _last_magz{0.0f}; #if defined(ENABLE_LOCKSTEP_SCHEDULER) px4::atomic _has_initialized {false}; #endif int _lockstep_component{-1}; DEFINE_PARAMETERS( (ParamInt) _param_mav_type, (ParamInt) _param_mav_sys_id, (ParamInt) _param_mav_comp_id ) };