Path: blob/master/libraries/AP_ExternalAHRS/AP_ExternalAHRS_SensAItion_Parser.h
13808 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/1415/*16SensAItion Protocol Parser17Handles binary protocol parsing (state machine, packet validation, checksums)18Separated from ArduPilot state management for testability19*/2021#pragma once2223#include <AP_HAL/AP_HAL.h>24#include <AP_Math/AP_Math.h>25#include <AP_Common/Location.h>2627class AP_ExternalAHRS_SensAItion_Parser28{29public:30// Configuration Mode defined in EAHRS_OPTIONS (Bit 1)31enum class ConfigMode {32IMU = 0, // IMU Only Mode (No ID byte, fixed 38 byte packet)33INTERLEAVED_INS = 1 // Interleaved Mode (Header -> ID -> Payload)34};3536// Type of data contained in a decoded Measurement37enum class MeasurementType {38UNINITIALIZED = 0,39IMU,40AHRS, // Maps to Packet 1 (Orientation)41INS // Maps to Packet 2 (Navigation)42};4344// Public Constants (Available to Driver)45static const uint16_t MAX_PACKET_SIZE = 1024;46static const uint8_t HEADER_BYTE = 0xFA;4748// Container for decoded data passed to Backend49struct Measurement {50MeasurementType type = MeasurementType::UNINITIALIZED;51uint64_t timestamp_us;5253// Packet 0 (IMU) Data54Vector3f acceleration_mss;55Vector3f angular_velocity_rads;56Vector3f magnetic_field_mgauss;57float temperature_degc;58float air_pressure_p;5960// Packet 1 (Orientation) Data61Quaternion orientation;6263// Packet 2 (INS) Data64Location location; // Lat/Lon/Alt65Vector3f velocity_ned; // North/East/Down (m/s)6667// Accuracy Metrics (Vectors as requested)68// ArduPilot often uses float for horiz/vert, but Vector3f is more flexible69// if the sensor provides 3-axis accuracy.70// Based on your config (AccLat, AccLon, AccPosD), we have 3 components.71Vector3f pos_accuracy; // North/East/Down (m)72Vector3f vel_accuracy; // North/East/Down (m/s)7374// Status & Health Flags75uint8_t alignment_status; // 1 = Align OK76uint8_t gnss1_fix;77uint8_t gnss2_fix;7879uint8_t num_sats_gnss1;80uint8_t num_sats_gnss2;8182// Time83uint32_t time_itow_ms; // GNSS time of week (ms)84uint16_t gps_week; // Calculated Week Number8586uint32_t error_flags; // Bitmask from sensor87uint8_t sensor_valid; // Validity bitmask88};8990// Constructor91AP_ExternalAHRS_SensAItion_Parser(ConfigMode mode);9293// Parse at most 'data_size' bytes from 'data', return # of bytes parsed.94// If we parsed less than 'data_size' bytes, 'meas' contains a measurement,95// otherwise it contains a valid measurement OR is uninitialized.96size_t parse_stream(const uint8_t* data, size_t data_size, Measurement& meas);9798// Number of parsed full length buffers that did not contain a valid packet99uint32_t get_parse_errors() const100{101return parse_errors;102}103104// Number of valid packets received during object lifetime105uint32_t get_valid_packets() const106{107return valid_packets;108}109110private:111// Payload Sizes (Excluding Header, ID, CRC)112static const uint8_t PAYLOAD_SIZE_IMU = 36; // Packet 0113static const uint8_t PAYLOAD_SIZE_QUAT = 16; // Packet 1114static const uint8_t PAYLOAD_SIZE_INS = 69; // Packet 2115116// Packet IDs (Interleaved Mode)117enum class PacketID : uint8_t {118IMU = 0x00,119AHRS = 0x01,120INS = 0x02,121UNKNOWN = 0xFF122};123124// Internal State Machine125enum class ParseState {126WAITING_HEADER,127WAITING_ID,128COLLECTING_PAYLOAD129};130131// Core Logic132void reset_parser(); // Does not reset packet and parse error counters133bool parse_single_byte(uint8_t byte); // Return true if it was the last byte of a valid packet134void handle_invalid_packet(); // Robust error recovery (memmove)135bool buffer_contains_valid_packet() const;136bool validate_checksum() const;137138// Decoders139void decode_packet(Measurement& measurement);140void decode_imu(const uint8_t* payload, Measurement& measurement);141void decode_ahrs(const uint8_t* payload, Measurement& measurement);142void decode_ins(const uint8_t* payload, Measurement& measurement);143144//Helpers145uint16_t calculate_gps_week(uint16_t year, uint8_t month, uint8_t day);146147// Members148ConfigMode config_mode;149ParseState parse_state;150PacketID current_packet_id;151152uint8_t packet_buffer[MAX_PACKET_SIZE];153size_t packet_buffer_len;154size_t target_payload_len;155156uint32_t valid_packets;157uint32_t parse_errors;158};159160161