Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/Replay/MsgHandler.cpp
9326 views
1
#include "MsgHandler.h"
2
3
void MsgHandler::add_field_type(char type, size_t size)
4
{
5
size_for_type_table[(type > 'A' ? (type-'A') : (type-'a'))] = size;
6
}
7
8
uint8_t MsgHandler::size_for_type(char type)
9
{
10
uint8_t ret = size_for_type_table[(uint8_t)(type > 'A' ? (type-'A') : (type-'a'))];
11
if (ret == 0) {
12
::printf("Unknown type (%c)\n", type);
13
abort();
14
}
15
return ret;
16
}
17
18
void MsgHandler::init_field_types()
19
{
20
add_field_type('b', sizeof(int8_t));
21
add_field_type('c', sizeof(int16_t));
22
add_field_type('d', sizeof(double));
23
add_field_type('e', sizeof(int32_t));
24
add_field_type('f', sizeof(float));
25
add_field_type('h', sizeof(int16_t));
26
add_field_type('i', sizeof(int32_t));
27
add_field_type('n', sizeof(char[4]));
28
add_field_type('B', sizeof(uint8_t));
29
add_field_type('C', sizeof(uint16_t));
30
add_field_type('E', sizeof(uint32_t));
31
add_field_type('H', sizeof(uint16_t));
32
add_field_type('I', sizeof(uint32_t));
33
add_field_type('L', sizeof(int32_t));
34
add_field_type('M', sizeof(uint8_t));
35
add_field_type('N', sizeof(char[16]));
36
add_field_type('Z', sizeof(char[64]));
37
add_field_type('q', sizeof(int64_t));
38
add_field_type('Q', sizeof(uint64_t));
39
}
40
41
struct MsgHandler::format_field_info *MsgHandler::find_field_info(const char *label)
42
{
43
for(uint8_t i=0; i<next_field; i++) {
44
if (streq(field_info[i].label, label)) {
45
return &field_info[i];
46
}
47
}
48
return nullptr;
49
}
50
51
MsgHandler::MsgHandler(const struct log_Format &_f) : next_field(0), f(_f)
52
{
53
init_field_types();
54
parse_format_fields();
55
}
56
57
void MsgHandler::add_field(const char *_label, uint8_t _type, uint8_t _offset,
58
uint8_t _length)
59
{
60
field_info[next_field].label = strdup(_label);
61
field_info[next_field].type = _type;
62
field_info[next_field].offset = _offset;
63
field_info[next_field].length = _length;
64
next_field++;
65
}
66
67
static char *get_string_field(char *field, uint8_t fieldlen)
68
{
69
char *ret = (char *)malloc(fieldlen+1);
70
memcpy(ret, field, fieldlen);
71
return ret;
72
}
73
74
void MsgHandler::parse_format_fields()
75
{
76
char *labels = get_string_field(f.labels, sizeof(f.labels));
77
char * arg = labels;
78
uint8_t label_offset = 0;
79
char *next_label;
80
uint8_t msg_offset = 3; // 3 bytes for the header
81
82
char *format = get_string_field(f.format, ARRAY_SIZE(f.format));
83
84
while ((next_label = strtok(arg, ",")) != NULL) {
85
if (label_offset > strlen(format)) {
86
printf("too few field times for labels %s (format=%s) (labels=%s)\n",
87
f.name, format, labels);
88
exit(1);
89
}
90
uint8_t field_type = format[label_offset];
91
uint8_t length = size_for_type(field_type);
92
add_field(next_label, field_type, msg_offset, length);
93
arg = NULL;
94
msg_offset += length;
95
label_offset++;
96
}
97
98
if (label_offset != strlen(format)) {
99
printf("too few labels for format (format=%s) (labels=%s)\n",
100
format, labels);
101
}
102
103
free(labels);
104
free(format);
105
}
106
107
bool MsgHandler::field_value(uint8_t *msg, const char *label, char *ret, uint8_t retlen)
108
{
109
struct format_field_info *info = find_field_info(label);
110
if (info == nullptr) {
111
::printf("No info for (%s)\n",label);
112
exit(1);
113
}
114
115
uint8_t offset = info->offset;
116
if (offset == 0) {
117
return false;
118
}
119
120
memset(ret, '\0', retlen);
121
122
memcpy(ret, &msg[offset], (retlen < info->length) ? retlen : info->length);
123
124
return true;
125
}
126
127
128
bool MsgHandler::field_value(uint8_t *msg, const char *label, Vector3f &ret)
129
{
130
const char *axes = "XYZ";
131
for(uint8_t i=0; i<next_field; i++) {
132
if (!strncmp(field_info[i].label, label, strlen(label)) &&
133
strlen(field_info[i].label) == strlen(label)+1) {
134
for (uint8_t j=0; j<3; j++) {
135
if (field_info[i].label[strlen(label)] == axes[j]) {
136
field_value_for_type_at_offset(msg,
137
field_info[i].type,
138
field_info[i].offset,
139
ret[j]);
140
break; // break from finding-label loop
141
}
142
}
143
}
144
if (i == next_field) {
145
return false; // not found
146
}
147
}
148
149
return true;
150
}
151
152
153
void MsgHandler::string_for_labels(char *buffer, uint32_t bufferlen)
154
{
155
memset(buffer, '\0', bufferlen);
156
bufferlen--;
157
158
char *pos = buffer;
159
for (uint8_t k=0; k<LOGREADER_MAX_FIELDS; k++) {
160
if (field_info[k].label != NULL) {
161
uint8_t remaining = bufferlen - (pos - buffer);
162
uint8_t label_length = strlen(field_info[k].label);
163
uint8_t required = label_length;
164
if (pos != buffer) { // room for a comma
165
required++;
166
}
167
if (required+1 > remaining) { // null termination
168
break;
169
}
170
171
if (pos != buffer) {
172
*pos++ = ',';
173
}
174
175
memcpy(pos, field_info[k].label, label_length);
176
pos += label_length;
177
}
178
}
179
}
180
181
void MsgHandler::location_from_msg(uint8_t *msg,
182
Location &loc,
183
const char *label_lat,
184
const char *label_long,
185
const char *label_alt)
186
{
187
loc.lat = require_field_int32_t(msg, label_lat);
188
loc.lng = require_field_int32_t(msg, label_long);
189
loc.set_alt_cm(require_field_int32_t(msg, label_alt), Location::AltFrame::ABSOLUTE);
190
}
191
192
void MsgHandler::ground_vel_from_msg(uint8_t *msg,
193
Vector3f &vel,
194
const char *label_speed,
195
const char *label_course,
196
const char *label_vz)
197
{
198
float ground_speed;
199
float ground_course;
200
// in older logs speed and course are integers
201
if (!field_value(msg, label_speed, ground_speed)) {
202
uint32_t speed_cms;
203
require_field(msg, label_speed, speed_cms);
204
ground_speed = speed_cms * 0.01f;
205
}
206
if (!field_value(msg, label_course, ground_course)) {
207
uint32_t course_cd;
208
require_field(msg, label_course, course_cd);
209
ground_course = course_cd * 0.01f;
210
}
211
require_field(msg, label_course, ground_course);
212
vel[0] = ground_speed*cosf(radians(ground_course));
213
vel[1] = ground_speed*sinf(radians(ground_course));
214
vel[2] = require_field_float(msg, label_vz);
215
}
216
217
void MsgHandler::attitude_from_msg(uint8_t *msg,
218
Vector3f &att,
219
const char *label_roll,
220
const char *label_pitch,
221
const char *label_yaw)
222
{
223
att[0] = require_field_int16_t(msg, label_roll) * 0.01f;
224
att[1] = require_field_int16_t(msg, label_pitch) * 0.01f;
225
att[2] = require_field_uint16_t(msg, label_yaw) * 0.01f;
226
}
227
228
void MsgHandler::field_not_found(uint8_t *msg, const char *label)
229
{
230
char all_labels[256];
231
uint8_t type = msg[2];
232
string_for_labels(all_labels, ARRAY_SIZE(all_labels));
233
::printf("Field (%s) not found for id=%d; options are (%s)\n",
234
label, type, all_labels);
235
abort();
236
}
237
238
void MsgHandler::require_field(uint8_t *msg, const char *label, char *buffer, uint8_t bufferlen)
239
{
240
if (! field_value(msg, label, buffer, bufferlen)) {
241
field_not_found(msg,label);
242
}
243
}
244
245
float MsgHandler::require_field_float(uint8_t *msg, const char *label)
246
{
247
float ret;
248
require_field(msg, label, ret);
249
return ret;
250
}
251
uint8_t MsgHandler::require_field_uint8_t(uint8_t *msg, const char *label)
252
{
253
uint8_t ret;
254
require_field(msg, label, ret);
255
return ret;
256
}
257
int32_t MsgHandler::require_field_int32_t(uint8_t *msg, const char *label)
258
{
259
int32_t ret;
260
require_field(msg, label, ret);
261
return ret;
262
}
263
uint16_t MsgHandler::require_field_uint16_t(uint8_t *msg, const char *label)
264
{
265
uint16_t ret;
266
require_field(msg, label, ret);
267
return ret;
268
}
269
int16_t MsgHandler::require_field_int16_t(uint8_t *msg, const char *label)
270
{
271
int16_t ret;
272
require_field(msg, label, ret);
273
return ret;
274
}
275
276