#pragma once
#include "AP_DAL_InertialSensor.h"
#include "AP_DAL_Baro.h"
#include "AP_DAL_GPS.h"
#include "AP_DAL_RangeFinder.h"
#include "AP_DAL_Compass.h"
#include "AP_DAL_Airspeed.h"
#include "AP_DAL_Beacon.h"
#include "AP_DAL_VisualOdom.h"
#include "LogStructure.h"
#include <stdio.h>
#include <stdint.h>
#include <cstddef>
#define DAL_CORE(c) AP::dal().logging_core(c)
class NavEKF2;
class NavEKF3;
class AP_DAL {
public:
enum class FrameType : uint8_t {
InitialiseFilterEKF2 = 1U<<0,
UpdateFilterEKF2 = 1U<<1,
InitialiseFilterEKF3 = 1<<2,
UpdateFilterEKF3 = 1<<3,
LogWriteEKF2 = 1<<4,
LogWriteEKF3 = 1<<5,
};
enum class Event : uint8_t {
resetGyroBias = 0,
resetHeightDatum = 1,
setTerrainHgtStable = 9,
unsetTerrainHgtStable = 10,
requestYawReset = 11,
checkLaneSwitch = 12,
setSourceSet0 = 13,
setSourceSet1 = 14,
setSourceSet2 = 15,
};
enum class VehicleClass : uint8_t {
UNKNOWN,
GROUND,
COPTER,
FIXED_WING,
SUBMARINE,
};
AP_DAL() {}
static AP_DAL *get_singleton() {
if (!_singleton) {
_singleton = NEW_NOTHROW AP_DAL();
}
return _singleton;
}
void start_frame(FrameType frametype);
void end_frame(void);
uint64_t micros64() const { return _RFRH.time_us; }
uint32_t micros() const { return _micros; }
uint32_t millis() const { return _millis; }
void log_event2(Event event);
void log_SetOriginLLH2(const Location &loc);
void log_writeDefaultAirSpeed2(const float aspeed, const float uncertainty);
void log_event3(Event event);
void log_SetOriginLLH3(const Location &loc);
void log_SetLatLng(const Location &loc, float posAccuracy, uint32_t timestamp_ms);
void log_writeDefaultAirSpeed3(const float aspeed, const float uncertainty);
void log_writeEulerYawAngle(float yawAngle, float yawAngleErr, uint32_t timeStamp_ms, uint8_t type);
enum class RFRNFlags {
ARMED = (1U<<0),
UNUSED = (1U<<1),
FLY_FORWARD = (1U<<2),
AHRS_AIRSPEED_SENSOR_ENABLED = (1U<<3),
OPTICALFLOW_ENABLED = (1U<<4),
WHEELENCODER_ENABLED = (1U<<5),
TAKEOFF_EXPECTED = (1U<<6),
TOUCHDOWN_EXPECTED = (1U<<7),
};
enum class EKFType : uint8_t {
EKF2 = 0,
EKF3 = 1,
};
bool ekf_low_time_remaining(EKFType etype, uint8_t core);
bool get_armed() const { return _RFRN.armed; }
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
uint32_t available_memory() const { return _RFRN.available_memory + 10240; }
#else
uint32_t available_memory() const { return _RFRN.available_memory; }
#endif
int8_t configured_ekf_type(void) const {
return _RFRN.ekf_type;
}
int snprintf(char* str, size_t size, const char *format, ...) const;
enum class MemoryType : uint8_t {
DMA_SAFE = 0,
FAST = 1,
};
void *malloc_type(size_t size, MemoryType mem_type) const;
void free_type(void *ptr, size_t size, MemoryType memtype) const;
AP_DAL_InertialSensor &ins() { return _ins; }
AP_DAL_Baro &baro() { return _baro; }
AP_DAL_GPS &gps() { return _gps; }
#if AP_RANGEFINDER_ENABLED
AP_DAL_RangeFinder *rangefinder() {
return _rangefinder;
}
#endif
AP_DAL_Airspeed *airspeed() {
return _airspeed;
}
#if AP_BEACON_ENABLED
AP_DAL_Beacon *beacon() {
return _beacon;
}
#endif
#if HAL_VISUALODOM_ENABLED
AP_DAL_VisualOdom *visualodom() {
return _visualodom;
}
#endif
AP_DAL_Compass &compass() { return _compass; }
bool airspeed_sensor_enabled(void) const {
return _RFRN.ahrs_airspeed_sensor_enabled;
}
float get_EAS2TAS(void) const {
return _RFRN.EAS2TAS;
}
VehicleClass get_vehicle_class(void) const {
return (VehicleClass)_RFRN.vehicle_class;
}
bool get_fly_forward(void) const {
return _RFRN.fly_forward;
}
bool get_takeoff_expected(void) const {
return _RFRN.takeoff_expected;
}
bool get_touchdown_expected(void) const {
return _RFRN.touchdown_expected;
}
void set_takeoff_expected();
const Vector3f &get_trim() const {
return _RFRN.ahrs_trim;
}
const Matrix3f &get_rotation_vehicle_body_to_autopilot_body(void) const {
return _rotation_vehicle_body_to_autopilot_body;
}
const class Location &get_home(void) const {
return _home;
}
uint32_t get_time_flying_ms(void) const {
return _RFRH.time_flying_ms;
}
bool opticalflow_enabled(void) const {
return _RFRN.opticalflow_enabled;
}
bool wheelencoder_enabled(void) const {
return _RFRN.wheelencoder_enabled;
}
void writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &rawFlowRates, const Vector2f &rawGyroRates, const uint32_t msecFlowMeas, const Vector3f &posOffset, float heightOverride);
void writeExtNavData(const Vector3f &pos, const Quaternion &quat, float posErr, float angErr, uint32_t timeStamp_ms, uint16_t delay_ms, uint32_t resetTime_ms);
void writeExtNavVelData(const Vector3f &vel, float err, uint32_t timeStamp_ms, uint16_t delay_ms);
void writeWheelOdom(float delAng, float delTime, uint32_t timeStamp_ms, const Vector3f &posOffset, float radius);
void writeBodyFrameOdom(float quality, const Vector3f &delPos, const Vector3f &delAng, float delTime, uint32_t timeStamp_ms, uint16_t delay_ms, const Vector3f &posOffset);
void writeTerrainData(float alt_m);
void handle_message(const log_RFRH &msg) {
_RFRH = msg;
_micros = _RFRH.time_us;
_millis = _RFRH.time_us / 1000UL;
}
void handle_message(const log_RFRN &msg) {
_RFRN = msg;
_home = {
msg.lat,
msg.lng,
msg.alt,
Location::AltFrame::ABSOLUTE
};
}
void handle_message(const log_RFRF &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_RISH &msg) {
_ins.handle_message(msg);
}
void handle_message(const log_RISI &msg) {
_ins.handle_message(msg);
}
void handle_message(const log_RASH &msg) {
if (_airspeed == nullptr) {
_airspeed = NEW_NOTHROW AP_DAL_Airspeed;
}
_airspeed->handle_message(msg);
}
void handle_message(const log_RASI &msg) {
if (_airspeed == nullptr) {
_airspeed = NEW_NOTHROW AP_DAL_Airspeed;
}
_airspeed->handle_message(msg);
}
void handle_message(const log_RBRH &msg) {
_baro.handle_message(msg);
}
void handle_message(const log_RBRI &msg) {
_baro.handle_message(msg);
}
void handle_message(const log_RRNH &msg) {
#if AP_RANGEFINDER_ENABLED
if (_rangefinder == nullptr) {
_rangefinder = NEW_NOTHROW AP_DAL_RangeFinder;
}
_rangefinder->handle_message(msg);
#endif
}
void handle_message(const log_RRNI &msg) {
#if AP_RANGEFINDER_ENABLED
if (_rangefinder == nullptr) {
_rangefinder = NEW_NOTHROW AP_DAL_RangeFinder;
}
_rangefinder->handle_message(msg);
#endif
}
void handle_message(const log_RGPH &msg) {
_gps.handle_message(msg);
}
void handle_message(const log_RGPI &msg) {
_gps.handle_message(msg);
}
void handle_message(const log_RGPJ &msg) {
_gps.handle_message(msg);
}
void handle_message(const log_RMGH &msg) {
_compass.handle_message(msg);
}
void handle_message(const log_RMGI &msg) {
_compass.handle_message(msg);
}
void handle_message(const log_RBCH &msg) {
#if AP_BEACON_ENABLED
if (_beacon == nullptr) {
_beacon = NEW_NOTHROW AP_DAL_Beacon;
}
_beacon->handle_message(msg);
#endif
}
void handle_message(const log_RBCI &msg) {
#if AP_BEACON_ENABLED
if (_beacon == nullptr) {
_beacon = NEW_NOTHROW AP_DAL_Beacon;
}
_beacon->handle_message(msg);
#endif
}
void handle_message(const log_RVOH &msg) {
#if HAL_VISUALODOM_ENABLED
if (_visualodom == nullptr) {
_visualodom = NEW_NOTHROW AP_DAL_VisualOdom;
}
_visualodom->handle_message(msg);
#endif
}
void handle_message(const log_ROFH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_REPH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_REVH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_RWOH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_RBOH &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_RSLL &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
void handle_message(const log_RTER &msg, NavEKF2 &ekf2, NavEKF3 &ekf3);
uint8_t logging_core(uint8_t c) const;
#if HAL_LOGGING_ENABLED
static void WriteLogMessage(enum LogMessages msg_type, void *msg, const void *old_msg, uint8_t msg_size);
#endif
private:
static AP_DAL *_singleton;
struct log_RFRH _RFRH;
struct log_RFRF _RFRF;
struct log_RFRN _RFRN;
struct log_ROFH _ROFH;
struct log_REPH _REPH;
struct log_REVH _REVH;
struct log_RWOH _RWOH;
struct log_RBOH _RBOH;
struct log_RSLL _RSLL;
struct log_RTER _RTER;
uint32_t _micros;
uint32_t _millis;
Matrix3f _rotation_vehicle_body_to_autopilot_body;
Location _home;
uint32_t _last_imu_time_us;
AP_DAL_InertialSensor _ins;
AP_DAL_Baro _baro;
AP_DAL_GPS _gps;
#if AP_RANGEFINDER_ENABLED
AP_DAL_RangeFinder *_rangefinder;
#endif
AP_DAL_Compass _compass;
AP_DAL_Airspeed *_airspeed;
#if AP_BEACON_ENABLED
AP_DAL_Beacon *_beacon;
#endif
#if HAL_VISUALODOM_ENABLED
AP_DAL_VisualOdom *_visualodom;
#endif
static bool logging_started;
static bool force_write;
bool ekf2_init_done;
bool ekf3_init_done;
void init_sensors(void);
bool init_done;
};
#if HAL_LOGGING_ENABLED
#define WRITE_REPLAY_BLOCK(sname,v) AP_DAL::WriteLogMessage(LOG_## sname ##_MSG, &v, nullptr, offsetof(log_ ##sname, _end))
#define WRITE_REPLAY_BLOCK_IFCHANGED(sname,v,old) do { static_assert(sizeof(v) == sizeof(old), "types must match"); \
AP_DAL::WriteLogMessage(LOG_## sname ##_MSG, &v, &old, offsetof(log_ ##sname, _end)); } \
while (0)
#else
#define WRITE_REPLAY_BLOCK(sname,v) do { (void)v; } while (false)
#define WRITE_REPLAY_BLOCK_IFCHANGED(sname,v,old) do { (void)old; } while (false)
#endif
namespace AP {
AP_DAL &dal();
};
void rprintf(const char *format, ...);