LCOV - code coverage report
Current view: top level - AP_DAL - AP_DAL.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 45 48 93.8 %
Date: 2026-09-09 11:02:08 Functions: 26 27 96.3 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : /*
       4             :   The DAL (Data Abstraction Layer) acts as an intermediary between ArduPilot's AHRS state estimators and its data sources.  Currently the only in-tree estimators using the DAL are the EKF2 and EKF3 estimators.
       5             : 
       6             :   When LOG_REPLAY is set to 1 all data entering the DAL is logged into ArduPilot's onboard ("dataflash") log.  LOG_DISARMED should be set when LOG_REPLAY is set.  Data is recorded in "frames" corresponding to a run of the EKF update functions.
       7             : 
       8             :   The logs produced in this manner can be "replayed" via a "replay" tool.  Data frames are read from the log and the estimator's update methods called to run an update cycle based on that data.
       9             : 
      10             :   In this way estimator problems can be reproduced from logs from real vehicles.
      11             : 
      12             :   Replay also allows for adjustment of the EKF's tunables to produce better estimates for given logs (and hopefully the vehicle the logs were produced from.
      13             : 
      14             :   See also https://ardupilot.club/dev/docs/testing-with-replay.html
      15             : */
      16             : 
      17             : #include "AP_DAL_InertialSensor.h"
      18             : #include "AP_DAL_Baro.h"
      19             : #include "AP_DAL_GPS.h"
      20             : #include "AP_DAL_RangeFinder.h"
      21             : #include "AP_DAL_Compass.h"
      22             : #include "AP_DAL_Airspeed.h"
      23             : #include "AP_DAL_Beacon.h"
      24             : #include "AP_DAL_VisualOdom.h"
      25             : 
      26             : #include "LogStructure.h"
      27             : 
      28             : #include <stdio.h>
      29             : #include <stdint.h>
      30             : #include <cstddef>
      31             : 
      32             : 
      33             : #define DAL_CORE(c) AP::dal().logging_core(c)
      34             : 
      35             : class NavEKF2;
      36             : class NavEKF3;
      37             : 
      38             : class AP_DAL {
      39             : public:
      40             : 
      41             :     enum class FrameType : uint8_t {
      42             :         InitialiseFilterEKF2 = 1U<<0,
      43             :         UpdateFilterEKF2 = 1U<<1,
      44             :         InitialiseFilterEKF3 = 1<<2,
      45             :         UpdateFilterEKF3 = 1<<3,
      46             :         LogWriteEKF2 = 1<<4,
      47             :         LogWriteEKF3 = 1<<5,
      48             :     };
      49             : 
      50             :     enum class Event : uint8_t {
      51             :         resetGyroBias             =  0,
      52             :         resetHeightDatum          =  1,
      53             :         //setInhibitGPS           =  2, // removed
      54             :         //setTakeoffExpected        =  3, // removed
      55             :         //unsetTakeoffExpected      =  4, // removed
      56             :         //setTouchdownExpected      =  5, // removed
      57             :         //unsetTouchdownExpected    =  6, // removed
      58             :         //setInhibitGpsVertVelUse   =  7, // removed
      59             :         //unsetInhibitGpsVertVelUse =  8, // removed
      60             :         setTerrainHgtStable       =  9,
      61             :         unsetTerrainHgtStable     = 10,
      62             :         requestYawReset           = 11,
      63             :         checkLaneSwitch           = 12,
      64             :         setSourceSet0             = 13,
      65             :         setSourceSet1             = 14,
      66             :         setSourceSet2             = 15,
      67             :     };
      68             : 
      69             :     // must remain the same as AP_AHRS_VehicleClass numbers-wise
      70             :     enum class VehicleClass : uint8_t {
      71             :         UNKNOWN,
      72             :         GROUND,
      73             :         COPTER,
      74             :         FIXED_WING,
      75             :         SUBMARINE,
      76             :     };
      77             : 
      78        2193 :     AP_DAL() {}
      79             : 
      80   265897692 :     static AP_DAL *get_singleton() {
      81   265897692 :         if (!_singleton) {
      82        2193 :             _singleton = NEW_NOTHROW AP_DAL();
      83             :         }
      84   265897692 :         return _singleton;
      85             :     }
      86             : 
      87             :     void start_frame(FrameType frametype);
      88             :     void end_frame(void);
      89    46415382 :     uint64_t micros64() const { return _RFRH.time_us; }
      90             :     uint32_t micros() const { return _micros; }
      91    92044889 :     uint32_t millis() const { return _millis; }
      92             : 
      93             :     void log_event2(Event event);
      94             :     void log_SetOriginLLH2(const Location &loc);
      95             :     void log_writeDefaultAirSpeed2(const float aspeed, const float uncertainty);
      96             : 
      97             :     void log_event3(Event event);
      98             :     void log_SetOriginLLH3(const Location &loc);
      99             :     void log_SetLatLng(const Location &loc, float posAccuracy, uint32_t timestamp_ms);
     100             : 
     101             :     void log_writeDefaultAirSpeed3(const float aspeed, const float uncertainty);
     102             :     void log_writeEulerYawAngle(float yawAngle, float yawAngleErr, uint32_t timeStamp_ms, uint8_t type);
     103             : 
     104             :     enum class RFRNFlags {
     105             :         ARMED = (1U<<0),
     106             :         UNUSED = (1U<<1),
     107             :         FLY_FORWARD = (1U<<2),
     108             :         AHRS_AIRSPEED_SENSOR_ENABLED = (1U<<3),
     109             :         OPTICALFLOW_ENABLED = (1U<<4),
     110             :         WHEELENCODER_ENABLED = (1U<<5),
     111             :         TAKEOFF_EXPECTED = (1U<<6),
     112             :         TOUCHDOWN_EXPECTED = (1U<<7),
     113             :     };
     114             : 
     115             :     // EKF ID for timing checks
     116             :     enum class EKFType : uint8_t {
     117             :         EKF2 = 0,
     118             :         EKF3 = 1,
     119             :     };
     120             : 
     121             :     // check if we are low on CPU for this core
     122             :     bool ekf_low_time_remaining(EKFType etype, uint8_t core);
     123             :     
     124             :     // returns armed state for the current frame
     125   200873827 :     bool get_armed() const { return _RFRN.armed; }
     126             : 
     127             :     // memory available at start of current frame.  While this could
     128             :     // potentially change as we go through the frame, the
     129             :     // ramifications of being out of memory are that you don't start
     130             :     // the EKF, so the simplicity of having one value for the entire
     131             :     // frame is worthwhile.
     132             : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
     133        7482 :     uint32_t available_memory() const { return _RFRN.available_memory + 10240; }
     134             : #else
     135           0 :     uint32_t available_memory() const { return _RFRN.available_memory; }
     136             : #endif
     137             : 
     138    38945869 :     int8_t configured_ekf_type(void) const {
     139    38945869 :         return _RFRN.ekf_type;
     140             :     }
     141             : 
     142             :     int snprintf(char* str, size_t size, const char *format, ...) const;
     143             : 
     144             :     // copied in AP_HAL/Util.h
     145             :     enum class MemoryType : uint8_t {
     146             :         DMA_SAFE = 0,
     147             :         FAST     = 1,
     148             :     };
     149             :     void *malloc_type(size_t size, MemoryType mem_type) const;
     150             :     void free_type(void *ptr, size_t size, MemoryType memtype) const;
     151             : 
     152   379652469 :     AP_DAL_InertialSensor &ins() { return _ins; }
     153   102726639 :     AP_DAL_Baro &baro() { return _baro; }
     154   145962459 :     AP_DAL_GPS &gps() { return _gps; }
     155             : 
     156             : #if AP_RANGEFINDER_ENABLED
     157    44136360 :     AP_DAL_RangeFinder *rangefinder() {
     158    44136360 :         return _rangefinder;
     159             :     }
     160             : #endif
     161             : 
     162   107475394 :     AP_DAL_Airspeed *airspeed() {
     163   107475394 :         return _airspeed;
     164             :     }
     165             : #if AP_BEACON_ENABLED
     166    23220913 :     AP_DAL_Beacon *beacon() {
     167    23220913 :         return _beacon;
     168             :     }
     169             : #endif
     170             : #if HAL_VISUALODOM_ENABLED
     171    39328608 :     AP_DAL_VisualOdom *visualodom() {
     172    39328608 :         return _visualodom;
     173             :     }
     174             : #endif
     175             : 
     176   454732030 :     AP_DAL_Compass &compass() { return _compass; }
     177             : 
     178             :     // random methods that AP_NavEKF3 wants to call on AHRS:
     179    29152712 :     bool airspeed_sensor_enabled(void) const {
     180    29152712 :         return _RFRN.ahrs_airspeed_sensor_enabled;
     181             :     }
     182             : 
     183             :     // get apparent to true airspeed ratio; this is a sensor input
     184             :     // to the EKFs, captured from the barometer's atmosphere model
     185             :     // in start_frame():
     186    31333561 :     float get_EAS2TAS(void) const {
     187    31333561 :         return _RFRN.EAS2TAS;
     188             :     }
     189             : 
     190    51851028 :     VehicleClass get_vehicle_class(void) const {
     191    51851028 :         return (VehicleClass)_RFRN.vehicle_class;
     192             :     }
     193             : 
     194   302870815 :     bool get_fly_forward(void) const {
     195   302870815 :         return _RFRN.fly_forward;
     196             :     }
     197             : 
     198    91771621 :     bool get_takeoff_expected(void) const {
     199    91771621 :         return _RFRN.takeoff_expected;
     200             :     }
     201             : 
     202    29953912 :     bool get_touchdown_expected(void) const {
     203    29953912 :         return _RFRN.touchdown_expected;
     204             :     }
     205             : 
     206             :     // for EKF usage to enable takeoff expected to true
     207             :     void set_takeoff_expected();
     208             : 
     209             :     // get ahrs trim
     210    48579808 :     const Vector3f &get_trim() const {
     211    48579808 :         return _RFRN.ahrs_trim;
     212             :     }
     213             : 
     214    42337748 :     const Matrix3f &get_rotation_vehicle_body_to_autopilot_body(void) const {
     215    42337748 :         return _rotation_vehicle_body_to_autopilot_body;
     216             :     }
     217             : 
     218             :     // get the home location. This is const to prevent any changes to
     219             :     // home without telling AHRS about the change
     220        3702 :     const class Location &get_home(void) const {
     221        3702 :         return _home;
     222             :     }
     223             : 
     224    47215099 :     uint32_t get_time_flying_ms(void) const {
     225    47215099 :         return _RFRH.time_flying_ms;
     226             :     }
     227             : 
     228        3996 :     bool opticalflow_enabled(void) const {
     229        3996 :         return _RFRN.opticalflow_enabled;
     230             :     }
     231             : 
     232           0 :     bool wheelencoder_enabled(void) const {
     233           0 :         return _RFRN.wheelencoder_enabled;
     234             :     }
     235             : 
     236             :     // log optical flow data
     237             :     void writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &rawFlowRates, const Vector2f &rawGyroRates, const uint32_t msecFlowMeas, const Vector3f &posOffset, float heightOverride);
     238             : 
     239             :     // log external nav data
     240             :     void writeExtNavData(const Vector3f &pos, const Quaternion &quat, float posErr, float angErr, uint32_t timeStamp_ms, uint16_t delay_ms, uint32_t resetTime_ms);
     241             :     void writeExtNavVelData(const Vector3f &vel, float err, uint32_t timeStamp_ms, uint16_t delay_ms);
     242             : 
     243             :     // log wheel odometry data
     244             :     void writeWheelOdom(float delAng, float delTime, uint32_t timeStamp_ms, const Vector3f &posOffset, float radius);
     245             :     void writeBodyFrameOdom(float quality, const Vector3f &delPos, const Vector3f &delAng, float delTime, uint32_t timeStamp_ms, uint16_t delay_ms, const Vector3f &posOffset);
     246             : 
     247             :     // Write terrain altitude (derived from SRTM) in meters above the origin
     248             :     void writeTerrainData(float alt_m);
     249             : 
     250             :     // Replay support:
     251             :     void handle_message(const log_RFRH &msg) {
     252             :         _RFRH = msg;
     253             :         _micros = _RFRH.time_us;
     254             :         _millis = _RFRH.time_us / 1000UL;
     255             :     }
     256             :     void handle_message(const log_RFRN &msg) {
     257             :         _RFRN = msg;
     258             :         _home = {
     259             :             msg.lat,
     260             :             msg.lng,
     261             :             msg.alt,
     262             :             Location::AltFrame::ABSOLUTE
     263             :         };
     264             :     }
     265             :     void handle_message(const log_RFRF &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     266             : 
     267             :     void handle_message(const log_RISH &msg) {
     268             :         _ins.handle_message(msg);
     269             :     }
     270             :     void handle_message(const log_RISI &msg) {
     271             :         _ins.handle_message(msg);
     272             :     }
     273             :     void handle_message(const log_RISJ &msg) {
     274             :         _ins.handle_message(msg);
     275             :     }
     276             : 
     277             :     void handle_message(const log_RASH &msg) {
     278             :         if (_airspeed == nullptr) {
     279             :             _airspeed = NEW_NOTHROW AP_DAL_Airspeed;
     280             :         }
     281             :         _airspeed->handle_message(msg);
     282             :     }
     283             :     void handle_message(const log_RASI &msg) {
     284             :         if (_airspeed == nullptr) {
     285             :             _airspeed = NEW_NOTHROW AP_DAL_Airspeed;
     286             :         }
     287             :         _airspeed->handle_message(msg);
     288             :     }
     289             : 
     290             :     void handle_message(const log_RBRH &msg) {
     291             :         _baro.handle_message(msg);
     292             :     }
     293             :     void handle_message(const log_RBRI &msg) {
     294             :         _baro.handle_message(msg);
     295             :     }
     296             : 
     297             :     void handle_message(const log_RRNH &msg) {
     298             : #if AP_RANGEFINDER_ENABLED
     299             :         if (_rangefinder == nullptr) {
     300             :             _rangefinder = NEW_NOTHROW AP_DAL_RangeFinder;
     301             :         }
     302             :         _rangefinder->handle_message(msg);
     303             : #endif
     304             :     }
     305             :     void handle_message(const log_RRNI &msg) {
     306             : #if AP_RANGEFINDER_ENABLED
     307             :         if (_rangefinder == nullptr) {
     308             :             _rangefinder = NEW_NOTHROW AP_DAL_RangeFinder;
     309             :         }
     310             :         _rangefinder->handle_message(msg);
     311             : #endif
     312             :     }
     313             : 
     314             :     void handle_message(const log_RGPH &msg) {
     315             :         _gps.handle_message(msg);
     316             :     }
     317             :     void handle_message(const log_RGPI &msg) {
     318             :         _gps.handle_message(msg);
     319             :     }
     320             :     void handle_message(const log_RGPJ &msg) {
     321             :         _gps.handle_message(msg);
     322             :     }
     323             : #if AP_DAL_RGPK_LOGGING_ENABLED
     324             :     void handle_message(const log_RGPK &msg) {
     325             :         _gps.handle_message(msg);
     326             :     }
     327             : #endif
     328             : 
     329             :     void handle_message(const log_RMGH &msg) {
     330             :         _compass.handle_message(msg);
     331             :     }
     332             :     void handle_message(const log_RMGI &msg) {
     333             :         _compass.handle_message(msg);
     334             :     }
     335             : 
     336             :     void handle_message(const log_RBCH &msg) {
     337             : #if AP_BEACON_ENABLED
     338             :         if (_beacon == nullptr) {
     339             :             _beacon = NEW_NOTHROW AP_DAL_Beacon;
     340             :         }
     341             :         _beacon->handle_message(msg);
     342             : #endif
     343             :     }
     344             :     void handle_message(const log_RBCI &msg) {
     345             : #if AP_BEACON_ENABLED
     346             :         if (_beacon == nullptr) {
     347             :             _beacon = NEW_NOTHROW AP_DAL_Beacon;
     348             :         }
     349             :         _beacon->handle_message(msg);
     350             : #endif
     351             :     }
     352             :     void handle_message(const log_RVOH &msg) {
     353             : #if HAL_VISUALODOM_ENABLED
     354             :         if (_visualodom == nullptr) {
     355             :             _visualodom = NEW_NOTHROW AP_DAL_VisualOdom;
     356             :         }
     357             :         _visualodom->handle_message(msg);
     358             : #endif
     359             :     }
     360             :     void handle_message(const log_ROFH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     361             :     void handle_message(const log_REPH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     362             :     void handle_message(const log_REVH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     363             :     void handle_message(const log_RWOH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     364             :     void handle_message(const log_RBOH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     365             :     void handle_message(const log_RSLL &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     366             :     void handle_message(const log_RTER &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
     367             : 
     368             :     // map core number for replay
     369             :     uint8_t logging_core(uint8_t c) const;
     370             : 
     371             : #if HAL_LOGGING_ENABLED
     372             :     // write out a DAL log message. If old_msg is non-null, then
     373             :     // only write if the content has changed
     374             :     static void WriteLogMessage(enum LogMessages msg_type, void *msg, const void *old_msg, uint8_t msg_size);
     375             : #endif
     376             : 
     377             : private:
     378             : 
     379             :     static AP_DAL *_singleton;
     380             : 
     381             :     // framing structures
     382             :     struct log_RFRH _RFRH;
     383             :     struct log_RFRF _RFRF;
     384             :     struct log_RFRN _RFRN;
     385             : 
     386             :     // push-based sensor structures
     387             :     struct log_ROFH _ROFH;
     388             :     struct log_REPH _REPH;
     389             :     struct log_REVH _REVH;
     390             :     struct log_RWOH _RWOH;
     391             :     struct log_RBOH _RBOH;
     392             :     struct log_RSLL _RSLL;
     393             :     struct log_RTER _RTER;
     394             : 
     395             :     // cached variables for speed:
     396             :     uint32_t _micros;
     397             :     uint32_t _millis;
     398             : 
     399             :     Matrix3f _rotation_vehicle_body_to_autopilot_body;
     400             :     Location _home;
     401             :     uint32_t _last_imu_time_us;
     402             : 
     403             :     AP_DAL_InertialSensor _ins;
     404             :     AP_DAL_Baro _baro;
     405             :     AP_DAL_GPS _gps;
     406             : #if AP_RANGEFINDER_ENABLED
     407             :     AP_DAL_RangeFinder *_rangefinder;
     408             : #endif
     409             :     AP_DAL_Compass _compass;
     410             :     AP_DAL_Airspeed *_airspeed;
     411             : #if AP_BEACON_ENABLED
     412             :     AP_DAL_Beacon *_beacon;
     413             : #endif
     414             : #if HAL_VISUALODOM_ENABLED
     415             :     AP_DAL_VisualOdom *_visualodom;
     416             : #endif
     417             : 
     418             :     static bool logging_started;
     419             :     static bool force_write;
     420             : 
     421             :     bool ekf2_init_done;
     422             :     bool ekf3_init_done;
     423             : 
     424             :     void init_sensors(void);
     425             :     bool init_done;
     426             : };
     427             : 
     428             : #if HAL_LOGGING_ENABLED
     429             : #define WRITE_REPLAY_BLOCK(sname,v) AP_DAL::WriteLogMessage(LOG_## sname ##_MSG, &v, nullptr, offsetof(log_ ##sname, _end))
     430             : #define WRITE_REPLAY_BLOCK_IFCHANGED(sname,v,old) do { static_assert(sizeof(v) == sizeof(old), "types must match"); \
     431             :                                                       AP_DAL::WriteLogMessage(LOG_## sname ##_MSG, &v, &old, offsetof(log_ ##sname, _end)); } \
     432             :                                                  while (0)
     433             : #else
     434             : #define WRITE_REPLAY_BLOCK(sname,v) do { (void)v; } while (false)
     435             : #define WRITE_REPLAY_BLOCK_IFCHANGED(sname,v,old) do { (void)old; } while (false)
     436             : #endif
     437             : 
     438             : namespace AP {
     439             :     AP_DAL &dal();
     440             : };
     441             : 
     442             : // replay printf for debugging
     443             : void rprintf(const char *format, ...);
     444             : 

Generated by: LCOV version 1.14