Skip to content

Commit 4c73ac3

Browse files
committed
uorb: use single byte for internal types in o_fields metadata
Reduces flash usage by ~9KB.
1 parent 9aaf6e3 commit 4c73ac3

File tree

8 files changed

+131
-36
lines changed

8 files changed

+131
-36
lines changed

msg/templates/uorb/msg.cpp.em

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ topic_name = spec.short_name
6161

6262
sorted_fields = sorted(spec.parsed_fields(), key=sizeof_field_type, reverse=True)
6363
struct_size, padding_end_size = add_padding_bytes(sorted_fields, search_path)
64-
topic_fields = ["%s %s" % (convert_type(field.type), field.name) for field in sorted_fields]
64+
topic_fields = ["%s %s" % (convert_type(field.type, True), field.name) for field in sorted_fields]
6565
}@
6666

6767
#include <inttypes.h>

msg/tools/px_generate_uorb_topic_helper.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@
6060
'char': 'char',
6161
}
6262

63+
type_map_short = {
64+
# We use some range outside of alpha-numeric and special characters.
65+
# This needs to match with orb_get_c_type()
66+
'int8': '\\x82',
67+
'int16': '\\x83',
68+
'int32': '\\x84',
69+
'int64': '\\x85',
70+
'uint8': '\\x86',
71+
'uint16': '\\x87',
72+
'uint32': '\\x88',
73+
'uint64': '\\x89',
74+
'float32': '\\x8a',
75+
'float64': '\\x8b',
76+
'bool': '\\x8c',
77+
'char': '\\x8d',
78+
}
79+
6380
type_serialize_map = {
6481
'int8': 'int8_t',
6582
'int16': 'int16_t',
@@ -204,7 +221,7 @@ def add_padding_bytes(fields, search_path):
204221
return (struct_size, num_padding_bytes)
205222

206223

207-
def convert_type(spec_type):
224+
def convert_type(spec_type, use_short_type=False):
208225
"""
209226
Convert from msg type to C type
210227
"""
@@ -215,7 +232,9 @@ def convert_type(spec_type):
215232

216233
msg_type, is_array, array_length = genmsg.msgs.parse_type(bare_type)
217234
c_type = msg_type
218-
if msg_type in type_map:
235+
if use_short_type and msg_type in type_map_short:
236+
c_type = type_map_short[msg_type]
237+
elif msg_type in type_map:
219238
c_type = type_map[msg_type]
220239
if is_array:
221240
return c_type + "[" + str(array_length) + "]"

platforms/common/uORB/uORB.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,35 @@ int orb_get_interval(int handle, unsigned *interval)
172172
{
173173
return uORB::Manager::get_instance()->orb_get_interval(handle, interval);
174174
}
175+
176+
const char *orb_get_c_type(unsigned char short_type)
177+
{
178+
// this matches with the uorb o_fields generator
179+
switch (short_type) {
180+
case 0x82: return "int8_t";
181+
182+
case 0x83: return "int16_t";
183+
184+
case 0x84: return "int32_t";
185+
186+
case 0x85: return "int64_t";
187+
188+
case 0x86: return "uint8_t";
189+
190+
case 0x87: return "uint16_t";
191+
192+
case 0x88: return "uint32_t";
193+
194+
case 0x89: return "uint64_t";
195+
196+
case 0x8a: return "float";
197+
198+
case 0x8b: return "double";
199+
200+
case 0x8c: return "bool";
201+
202+
case 0x8d: return "char";
203+
}
204+
205+
return nullptr;
206+
}

platforms/common/uORB/uORB.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
*
3232
****************************************************************************/
3333

34-
#ifndef _UORB_UORB_H
35-
#define _UORB_UORB_H
34+
#pragma once
3635

3736
/**
3837
* @file uORB.h
@@ -235,6 +234,12 @@ extern int orb_set_interval(int handle, unsigned interval) __EXPORT;
235234
*/
236235
extern int orb_get_interval(int handle, unsigned *interval) __EXPORT;
237236

237+
/**
238+
* Returns the C type string from a short type in o_fields metadata, or nullptr
239+
* if not a short type
240+
*/
241+
const char *orb_get_c_type(unsigned char short_type);
242+
238243
__END_DECLS
239244

240245
/* Diverse uORB header defines */ //XXX: move to better location
@@ -245,4 +250,3 @@ typedef uint8_t hil_state_t;
245250
typedef uint8_t navigation_state_t;
246251
typedef uint8_t switch_pos_t;
247252

248-
#endif /* _UORB_UORB_H */

src/modules/logger/logged_topics.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -362,15 +362,6 @@ void LoggedTopics::add_mission_topic(const char *name, uint16_t interval_ms)
362362

363363
bool LoggedTopics::add_topic(const orb_metadata *topic, uint16_t interval_ms, uint8_t instance)
364364
{
365-
size_t fields_len = strlen(topic->o_fields) + strlen(topic->o_name) + 1; //1 for ':'
366-
367-
if (fields_len > sizeof(ulog_message_format_s::format)) {
368-
PX4_WARN("skip topic %s, format string is too large: %zu (max is %zu)", topic->o_name, fields_len,
369-
sizeof(ulog_message_format_s::format));
370-
371-
return false;
372-
}
373-
374365
if (_subscriptions.count >= MAX_TOPICS_NUM) {
375366
PX4_WARN("Too many subscriptions, failed to add: %s %" PRIu8, topic->o_name, instance);
376367
return false;

src/modules/logger/logger.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,37 @@ void Logger::write_format(LogType type, const orb_metadata &meta, WrittenFormats
16261626
PX4_DEBUG("writing format for %s", meta.o_name);
16271627

16281628
// Write the current format (we don't need to check if we already added it to written_formats)
1629-
int format_len = snprintf(msg.format, sizeof(msg.format), "%s:%s", meta.o_name, meta.o_fields);
1629+
int format_len = snprintf(msg.format, sizeof(msg.format), "%s:", meta.o_name);
1630+
1631+
for (int format_idx = 0; meta.o_fields[format_idx] != 0;) {
1632+
const char *end_field = strchr(meta.o_fields + format_idx, ';');
1633+
1634+
if (!end_field) {
1635+
PX4_ERR("Format error in %s", meta.o_fields);
1636+
return;
1637+
}
1638+
1639+
const char *c_type = orb_get_c_type(meta.o_fields[format_idx]);
1640+
1641+
if (c_type) {
1642+
format_len += snprintf(msg.format + format_len, sizeof(msg.format) - format_len, "%s", c_type);
1643+
++format_idx;
1644+
}
1645+
1646+
int len = end_field - (meta.o_fields + format_idx) + 1;
1647+
1648+
if (len >= (int)sizeof(msg.format) - format_len) {
1649+
PX4_WARN("skip topic %s, format string is too large, max is %zu", meta.o_name,
1650+
sizeof(ulog_message_format_s::format));
1651+
return;
1652+
}
1653+
1654+
memcpy(msg.format + format_len, meta.o_fields + format_idx, len);
1655+
format_len += len;
1656+
format_idx += len;
1657+
}
1658+
1659+
msg.format[format_len] = '\0';
16301660
size_t msg_size = sizeof(msg) - sizeof(msg.format) + format_len;
16311661
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
16321662

@@ -1637,7 +1667,7 @@ void Logger::write_format(LogType type, const orb_metadata &meta, WrittenFormats
16371667
}
16381668

16391669
// Now go through the fields and check for nested type usages.
1640-
// o_fields looks like this for example: "uint64_t timestamp;uint8_t[5] array;"
1670+
// o_fields looks like this for example: "<chr> timestamp;<chr>[5] array;"
16411671
const char *fmt = meta.o_fields;
16421672

16431673
while (fmt && *fmt) {
@@ -1670,20 +1700,7 @@ void Logger::write_format(LogType type, const orb_metadata &meta, WrittenFormats
16701700
type_name[type_length] = '\0';
16711701

16721702
// ignore built-in types
1673-
if (strcmp(type_name, "int8_t") != 0 &&
1674-
strcmp(type_name, "uint8_t") != 0 &&
1675-
strcmp(type_name, "int16_t") != 0 &&
1676-
strcmp(type_name, "uint16_t") != 0 &&
1677-
strcmp(type_name, "int16_t") != 0 &&
1678-
strcmp(type_name, "uint16_t") != 0 &&
1679-
strcmp(type_name, "int32_t") != 0 &&
1680-
strcmp(type_name, "uint32_t") != 0 &&
1681-
strcmp(type_name, "int64_t") != 0 &&
1682-
strcmp(type_name, "uint64_t") != 0 &&
1683-
strcmp(type_name, "float") != 0 &&
1684-
strcmp(type_name, "double") != 0 &&
1685-
strcmp(type_name, "bool") != 0 &&
1686-
strcmp(type_name, "char") != 0) {
1703+
if (orb_get_c_type(type_name[0]) == nullptr) {
16871704

16881705
// find orb meta for type
16891706
const orb_metadata *const *topics = orb_get_topics();

src/modules/replay/Replay.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,36 @@ Replay::readFormat(std::ifstream &file, uint16_t msg_size)
336336
return true;
337337
}
338338

339+
340+
string Replay::parseOrbFields(const string &fields)
341+
{
342+
string ret{};
343+
344+
// convert o_fields from "<chr> timestamp;<chr>[5] array;" to "uint64_t timestamp;int8_t[5] array;"
345+
for (int format_idx = 0; format_idx < (int)fields.length();) {
346+
const char *end_field = strchr(fields.c_str() + format_idx, ';');
347+
348+
if (!end_field) {
349+
PX4_ERR("Format error in %s", fields.c_str());
350+
return "";
351+
}
352+
353+
const char *c_type = orb_get_c_type(fields[format_idx]);
354+
355+
if (c_type) {
356+
string str_type = c_type;
357+
ret += str_type;
358+
++format_idx;
359+
}
360+
361+
int len = end_field - (fields.c_str() + format_idx) + 1;
362+
ret += fields.substr(format_idx, len);
363+
format_idx += len;
364+
}
365+
366+
return ret;
367+
}
368+
339369
bool
340370
Replay::readAndAddSubscription(std::ifstream &file, uint16_t msg_size)
341371
{
@@ -371,12 +401,12 @@ Replay::readAndAddSubscription(std::ifstream &file, uint16_t msg_size)
371401
// FIXME: this should check recursively, all used nested types
372402
string file_format = _file_formats[topic_name];
373403

374-
std::string orb_fields(orb_meta->o_fields);
404+
const string orb_fields = parseOrbFields(orb_meta->o_fields);
375405

376406
if (file_format != orb_fields) {
377407
// check if we have a compatibility conversion available
378408
if (topic_name == "sensor_combined") {
379-
if (string(orb_meta->o_fields) == "uint64_t timestamp;float[3] gyro_rad;uint32_t gyro_integral_dt;"
409+
if (orb_fields == "uint64_t timestamp;float[3] gyro_rad;uint32_t gyro_integral_dt;"
380410
"int32_t accelerometer_timestamp_relative;float[3] accelerometer_m_s2;"
381411
"uint32_t accelerometer_integral_dt" &&
382412
file_format == "uint64_t timestamp;float[3] gyro_rad;float gyro_integral_dt;"
@@ -390,9 +420,9 @@ Replay::readAndAddSubscription(std::ifstream &file, uint16_t msg_size)
390420
int unused;
391421

392422
if (findFieldOffset(file_format, "gyro_integral_dt", gyro_integral_dt_offset_log, unused) &&
393-
findFieldOffset(orb_meta->o_fields, "gyro_integral_dt", gyro_integral_dt_offset_intern, unused) &&
423+
findFieldOffset(orb_fields, "gyro_integral_dt", gyro_integral_dt_offset_intern, unused) &&
394424
findFieldOffset(file_format, "accelerometer_integral_dt", accelerometer_integral_dt_offset_log, unused) &&
395-
findFieldOffset(orb_meta->o_fields, "accelerometer_integral_dt", accelerometer_integral_dt_offset_intern, unused)) {
425+
findFieldOffset(orb_fields, "accelerometer_integral_dt", accelerometer_integral_dt_offset_intern, unused)) {
396426

397427
compat = new CompatSensorCombinedDtType(gyro_integral_dt_offset_log, gyro_integral_dt_offset_intern,
398428
accelerometer_integral_dt_offset_log, accelerometer_integral_dt_offset_intern);
@@ -449,7 +479,7 @@ Replay::readAndAddSubscription(std::ifstream &file, uint16_t msg_size)
449479

450480
//find the timestamp offset
451481
int field_size;
452-
bool timestamp_found = findFieldOffset(orb_meta->o_fields, "timestamp", subscription->timestamp_offset, field_size);
482+
bool timestamp_found = findFieldOffset(orb_fields, "timestamp", subscription->timestamp_offset, field_size);
453483

454484
if (!timestamp_found) {
455485
delete subscription;

src/modules/replay/Replay.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ class Replay : public ModuleBase<Replay>
277277

278278
void setUserParams(const char *filename);
279279

280+
std::string parseOrbFields(const std::string &fields);
281+
280282
static char *_replay_file;
281283
};
282284

0 commit comments

Comments
 (0)