Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/Replay/MsgHandler.h
Views: 1862
#pragma once12#include <AP_Logger/AP_Logger.h>3#include "VehicleType.h"45#include <stdio.h>67// ignore cast errors in this case to keep complexity down8// on x86 where replay is run we don't care about cast alignment9#pragma GCC diagnostic ignored "-Wcast-align"1011#define LOGREADER_MAX_FIELDS 301213#define streq(x, y) (!strcmp(x, y))1415class MsgHandler {16public:17// constructor - create a parser for a MavLink message format18MsgHandler(const struct log_Format &f);1920// retrieve a comma-separated list of all labels21void string_for_labels(char *buffer, uint32_t bufferlen);2223// field_value - retrieve the value of a field from the supplied message24// these return false if the field was not found25template<typename R>26bool field_value(uint8_t *msg, const char *label, R &ret);2728bool field_value(uint8_t *msg, const char *label, Vector3f &ret);29bool field_value(uint8_t *msg, const char *label,30char *buffer, uint8_t bufferlen);3132template <typename R>33void require_field(uint8_t *msg, const char *label, R &ret)34{35if (! field_value(msg, label, ret)) {36field_not_found(msg, label);37}38}39void require_field(uint8_t *msg, const char *label, char *buffer, uint8_t bufferlen);40float require_field_float(uint8_t *msg, const char *label);41uint8_t require_field_uint8_t(uint8_t *msg, const char *label);42int32_t require_field_int32_t(uint8_t *msg, const char *label);43uint16_t require_field_uint16_t(uint8_t *msg, const char *label);44int16_t require_field_int16_t(uint8_t *msg, const char *label);4546private:4748void add_field(const char *_label, uint8_t _type, uint8_t _offset,49uint8_t length);5051template<typename R>52void field_value_for_type_at_offset(uint8_t *msg, uint8_t type,53uint8_t offset, R &ret);5455struct format_field_info { // parsed field information56char *label;57uint8_t type;58uint8_t offset;59uint8_t length;60};61struct format_field_info field_info[LOGREADER_MAX_FIELDS];6263uint8_t next_field;64size_t size_for_type_table[52]; // maps field type (e.g. 'f') to e.g 4 bytes6566struct format_field_info *find_field_info(const char *label);6768void parse_format_fields();69void init_field_types();70void add_field_type(char type, size_t size);71uint8_t size_for_type(char type);7273protected:74struct log_Format f; // the format we are a parser for7576void location_from_msg(uint8_t *msg, Location &loc, const char *label_lat,77const char *label_long, const char *label_alt);7879void ground_vel_from_msg(uint8_t *msg,80Vector3f &vel,81const char *label_speed,82const char *label_course,83const char *label_vz);8485void attitude_from_msg(uint8_t *msg,86Vector3f &att,87const char *label_roll,88const char *label_pitch,89const char *label_yaw);90[[noreturn]] void field_not_found(uint8_t *msg, const char *label);91};9293template<typename R>94bool MsgHandler::field_value(uint8_t *msg, const char *label, R &ret)95{96struct format_field_info *info = find_field_info(label);97if (info == NULL) {98return false;99}100101uint8_t offset = info->offset;102if (offset == 0) {103return false;104}105106field_value_for_type_at_offset(msg, info->type, offset, ret);107108return true;109}110111112template<typename R>113inline void MsgHandler::field_value_for_type_at_offset(uint8_t *msg,114uint8_t type,115uint8_t offset,116R &ret)117{118/* we register the types - add_field_type - so can we do without119* this switch statement somehow? */120switch (type) {121case 'B':122ret = (R)(((uint8_t*)&msg[offset])[0]);123break;124case 'c':125case 'h':126ret = (R)(((int16_t*)&msg[offset])[0]);127break;128case 'H':129ret = (R)(((uint16_t*)&msg[offset])[0]);130break;131case 'C':132ret = (R)(((uint16_t*)&msg[offset])[0]);133break;134case 'f':135ret = (R)(((float*)&msg[offset])[0]);136break;137case 'I':138case 'E':139ret = (R)(((uint32_t*)&msg[offset])[0]);140break;141case 'L':142case 'e':143ret = (R)(((int32_t*)&msg[offset])[0]);144break;145case 'q':146ret = (R)(((int64_t*)&msg[offset])[0]);147break;148case 'Q':149ret = (R)(((uint64_t*)&msg[offset])[0]);150break;151default:152::printf("Unhandled format type (%c)\n", type);153exit(1);154}155}156157158