34 #include <px4_platform_common/px4_config.h> 35 #include <px4_platform_common/console_buffer.h> 54 #include <px4_platform_common/getopt.h> 55 #include <px4_platform_common/log.h> 56 #include <px4_platform_common/posix.h> 57 #include <px4_platform_common/sem.h> 58 #include <px4_platform_common/shutdown.h> 59 #include <px4_platform_common/tasks.h> 68 #if defined(__PX4_POSIX) && !defined(__PX4_DARWIN) 73 #if defined(__PX4_DARWIN) 86 volatile bool watchdog_triggered =
false;
108 if (px4_sem_getvalue(&data->
semaphore, &semaphore_value) == 0 && semaphore_value > 1) {
122 if (*(
char *)&num != 1) {
123 PX4_ERR(
"Logger only works on little endian!\n");
144 if (!strcmp(argv[0],
"on")) {
145 get_instance()->set_arm_override(
true);
149 if (!strcmp(argv[0],
"off")) {
150 get_instance()->set_arm_override(
false);
159 _task_id = px4_task_spawn_cmd(
"logger",
161 SCHED_PRIORITY_LOG_CAPTURE,
163 (px4_main_t)&run_trampoline,
164 (
char *
const *)argv);
176 PX4_INFO(
"Running in mode: %s", configured_backend_mode());
178 bool is_logging =
false;
181 PX4_INFO(
"Full File Logging Running:");
187 PX4_INFO(
"Mission File Logging Running:");
193 PX4_INFO(
"Mavlink Logging Running (Full log)");
198 PX4_INFO(
"Not logging");
213 float kibibytes = _writer.get_total_written_file(type) / 1024.0f;
214 float mebibytes = kibibytes / 1024.0f;
217 PX4_INFO(
"Log file: %s/%s/%s", LOG_ROOT[(
int)type], _file_name[(
int)type].log_dir, _file_name[(
int)type].log_file_name);
219 if (mebibytes < 0.1
f) {
220 PX4_INFO(
"Wrote %4.2f KiB (avg %5.2f KiB/s)", (
double)kibibytes, (
double)(kibibytes / seconds));
223 PX4_INFO(
"Wrote %4.2f MiB (avg %5.2f KiB/s)", (
double)mebibytes, (
double)(kibibytes / seconds));
226 PX4_INFO(
"Since last status: dropouts: %zu (max len: %.3f s), max used buffer: %zu / %zu B",
235 uint32_t log_interval = 3500;
236 int log_buffer_size = 12 * 1024;
237 bool log_on_start =
false;
238 bool log_until_shutdown =
false;
240 bool error_flag =
false;
241 bool log_name_timestamp =
false;
243 const char *poll_topic =
nullptr;
247 const char *myoptarg =
nullptr;
249 while ((ch = px4_getopt(argc, argv,
"r:b:etfm:p:x", &myoptind, &myoptarg)) != EOF) {
252 unsigned long r = strtoul(myoptarg,
nullptr, 10);
258 log_interval = 1e6 / r;
271 unsigned long s = strtoul(myoptarg,
nullptr, 10);
277 log_buffer_size = 1024 * s;
282 log_name_timestamp =
true;
287 log_until_shutdown =
true;
291 if (!strcmp(myoptarg,
"file")) {
294 }
else if (!strcmp(myoptarg,
"mavlink")) {
297 }
else if (!strcmp(myoptarg,
"all")) {
301 PX4_ERR(
"unknown mode: %s", myoptarg);
308 poll_topic = myoptarg;
316 PX4_WARN(
"unrecognized flag");
323 if (log_until_shutdown) {
335 Logger *logger =
new Logger(backend, log_buffer_size, log_interval, poll_topic, log_mode, log_name_timestamp);
337 #if defined(DBGPRINT) && defined(__PX4_NUTTX) 338 struct mallinfo alloc_info = mallinfo();
339 PX4_INFO(
"largest free chunk: %d bytes", alloc_info.mxordblk);
340 PX4_INFO(
"remaining free heap: %d bytes", alloc_info.fordblks);
343 if (logger ==
nullptr) {
344 PX4_ERR(
"alloc failed");
349 const char *logfile = getenv(px4::replay::ENV_FILENAME);
364 LogMode log_mode,
bool log_name_timestamp) :
366 _log_name_timestamp(log_name_timestamp),
367 _writer(backend, buffer_size),
368 _log_interval(log_interval)
375 if (poll_topic_name) {
379 if (strcmp(poll_topic_name, topics[i]->o_name) == 0) {
386 PX4_ERR(
"Failed to find topic %s", poll_topic_name);
405 get_instance()->request_stop();
415 size_t fields_len = strlen(topic->
o_fields) + strlen(topic->
o_name) + 1;
418 PX4_WARN(
"skip topic %s, format string is too large: %zu (max is %zu)", topic->
o_name, fields_len,
428 PX4_WARN(
"Too many subscriptions, failed to add: %s %d", topic->
o_name, instance);
445 if (strcmp(name, topics[i]->o_name) == 0) {
446 bool already_added =
false;
452 PX4_DEBUG(
"logging topic %s(%d), interval: %i, already added, only setting interval",
453 topics[i]->o_name, instance, interval_ms);
458 already_added =
true;
463 if (!already_added) {
464 subscription =
add_topic(topics[i], interval_ms, instance);
465 PX4_DEBUG(
"logging topic: %s(%d), interval: %i", topics[i]->o_name, instance, interval_ms);
471 return (subscription !=
nullptr);
488 bool updated =
false;
491 updated = sub.
update(buffer);
493 }
else if (try_to_subscribe) {
502 updated = sub.
copy(buffer);
525 add_topic(
"manual_control_setpoint", 200);
529 add_topic(
"position_controller_status", 500);
530 add_topic(
"position_setpoint_triplet", 200);
539 add_topic(
"vehicle_angular_velocity", 20);
541 add_topic(
"vehicle_attitude_setpoint", 100);
543 add_topic(
"vehicle_global_position", 200);
545 add_topic(
"vehicle_local_position", 100);
546 add_topic(
"vehicle_local_position_setpoint", 100);
560 #ifdef CONFIG_ARCH_BOARD_PX4_SITL 562 add_topic(
"actuator_controls_virtual_fw");
563 add_topic(
"actuator_controls_virtual_mc");
564 add_topic(
"fw_virtual_attitude_setpoint");
565 add_topic(
"mc_virtual_attitude_setpoint");
569 add_topic(
"vehicle_angular_velocity", 10);
570 add_topic(
"vehicle_attitude_groundtruth", 10);
571 add_topic(
"vehicle_global_position_groundtruth", 100);
572 add_topic(
"vehicle_local_position_groundtruth", 100);
618 add_topic(
"vehicle_visual_odometry_aligned");
643 add_topic(
"onboard_computer_status", 200);
645 add_topic(
"vehicle_trajectory_waypoint", 200);
646 add_topic(
"vehicle_trajectory_waypoint_desired", 200);
647 add_topic(
"vehicle_visual_odometry", 30);
663 FILE *fp = fopen(fname,
"r");
675 if (fgets(line,
sizeof(line), fp) ==
nullptr) {
680 if ((strlen(line) < 2) || (line[0] ==
'#')) {
686 uint32_t interval_ms = 0;
687 int nfields = sscanf(line,
"%s %u", topic_name, &interval_ms);
690 int name_len = strlen(topic_name);
692 if (name_len > 0 && topic_name[name_len - 1] ==
',') {
693 topic_name[name_len - 1] =
'\0';
697 if (
add_topic(topic_name, interval_ms)) {
701 PX4_ERR(
"Failed to add topic %s", topic_name);
719 default:
return "several";
745 if ((int32_t)sdlog_profile == 0) {
746 PX4_WARN(
"No logging profile selected. Using default set");
789 PX4_ERR(
"Max num mission topics exceeded");
807 if (mkdir_ret == 0) {
808 PX4_INFO(
"log root dir created: %s",
LOG_ROOT[(
int)LogType::Full]);
810 }
else if (errno != EEXIST) {
811 PX4_ERR(
"failed creating log root dir: %s (%i)",
LOG_ROOT[(
int)LogType::Full], errno);
818 int32_t max_log_dirs_to_keep = 0;
825 _file_name[(
int)LogType::Full].sess_dir_index) == 1) {
833 int32_t mission_log_mode = 0;
842 if (mkdir_ret != 0 && errno != EEXIST) {
843 PX4_ERR(
"failed creating log root dir: %s (%i)",
LOG_ROOT[(
int)LogType::Mission], errno);
851 PX4_INFO(
"logging %d topics from logger_topics.txt", ntopics);
858 int max_msg_size = 0;
862 if (subscription.get_topic()->o_size > max_msg_size) {
863 max_msg_size = subscription.get_topic()->o_size;
886 PX4_ERR(
"failed to alloc message buffer");
893 PX4_ERR(
"writer init failed");
899 uint32_t total_bytes = 0;
910 px4_sem_init(&timer_callback_data.
semaphore, 0, 0);
912 px4_sem_setprotocol(&timer_callback_data.
semaphore, SEM_PRIO_NONE);
914 int polling_topic_sub = -1;
919 if (polling_topic_sub < 0) {
920 PX4_ERR(
"Failed to subscribe (%i)", errno);
927 const pid_t pid_self = getpid();
940 int next_subscribe_topic_index = -1;
942 while (!should_exit()) {
947 if (logging_started) {
981 if (parameter_update_sub.
updated()) {
984 parameter_update_sub.
copy(&pupdate);
999 const bool try_to_subscribe = (sub_idx == next_subscribe_topic_index);
1005 const uint16_t write_msg_id = sub.msg_id;
1020 total_bytes += msg_size;
1030 if (delta_time > 0) {
1047 const char *message = (
const char *)log_message.
text;
1048 int message_len = strlen(message);
1050 if (message_len > 0) {
1099 if (next_subscribe_topic_index != -1) {
1100 if (++next_subscribe_topic_index >= (
int)_subscriptions.size()) {
1101 next_subscribe_topic_index = -1;
1105 }
else if (loop_time > next_subscribe_check) {
1106 next_subscribe_topic_index = 0;
1116 if (next_subscribe_topic_index != -1) {
1117 if (!_subscriptions[next_subscribe_topic_index].valid()) {
1118 _subscriptions[next_subscribe_topic_index].subscribe();
1121 if (++next_subscribe_topic_index >= (
int)_subscriptions.size()) {
1122 next_subscribe_topic_index = -1;
1126 }
else if (loop_time > next_subscribe_check) {
1127 next_subscribe_topic_index = 0;
1132 if (polling_topic_sub >= 0) {
1133 px4_pollfd_struct_t fds[1];
1134 fds[0].fd = polling_topic_sub;
1135 fds[0].events = POLLIN;
1139 PX4_ERR(
"poll failed (%i)", pret);
1141 }
else if (pret != 0) {
1142 if (fds[0].revents & POLLIN) {
1156 while (px4_sem_wait(&timer_callback_data.
semaphore) != 0) {}
1164 px4_sem_destroy(&timer_callback_data.
semaphore);
1169 if (polling_topic_sub >= 0) {
1187 struct mallinfo alloc_info = mallinfo();
1188 double throughput = total_bytes / deltat;
1189 PX4_INFO(
"%8.1f kB/s, %zu highWater, %d dropouts, %5.3f sec max, free heap: %d",
1191 (
double)
_statistics[0].max_dropout_duration, alloc_info.fordblks);
1205 bool want_start =
false;
1206 bool want_stop =
false;
1263 }
else if (want_stop) {
1282 if (command.
command == vehicle_command_s::VEHICLE_CMD_LOGGING_START) {
1284 if ((
int)(command.
param1 + 0.5f) != 0) {
1292 ack_vehicle_command(&command, vehicle_command_s::VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED);
1295 }
else if (command.
command == vehicle_command_s::VEHICLE_CMD_LOGGING_STOP) {
1335 int n = snprintf(log_dir, log_dir_len,
"%s/",
LOG_ROOT[(
int)type]);
1337 if (n >= log_dir_len) {
1338 PX4_ERR(
"log path too long");
1344 strncpy(log_dir + n, file_name.
log_dir, log_dir_len - n);
1345 int mkdir_ret = mkdir(log_dir, S_IRWXU | S_IRWXG | S_IRWXO);
1347 if (mkdir_ret !=
OK && errno != EEXIST) {
1348 PX4_ERR(
"failed creating new dir: %s", log_dir);
1356 strncpy(log_dir + n, file_name.
log_dir, log_dir_len - n);
1365 PX4_ERR(
"log path too long (%i)", n);
1369 strncpy(log_dir + n, file_name.
log_dir, log_dir_len - n);
1370 int mkdir_ret = mkdir(log_dir, S_IRWXU | S_IRWXG | S_IRWXO);
1372 if (mkdir_ret == 0) {
1373 PX4_DEBUG(
"log dir created: %s", log_dir);
1376 }
else if (errno != EEXIST) {
1377 PX4_ERR(
"failed creating new dir: %s (%i)", log_dir, errno);
1388 return strlen(log_dir);
1394 bool time_ok =
false;
1397 int32_t utc_offset = 0;
1407 const char *replay_suffix =
"";
1410 replay_suffix =
"_replayed";
1413 char *log_file_name =
_file_name[(int)type].log_file_name;
1422 char log_file_name_time[16] =
"";
1423 strftime(log_file_name_time,
sizeof(log_file_name_time),
"%H_%M_%S", &tt);
1425 snprintf(file_name + n, file_name_size - n,
"/%s", log_file_name);
1428 int n =
create_log_dir(type,
nullptr, file_name, file_name_size);
1434 uint16_t file_number = 1;
1440 snprintf(file_name + n, file_name_size - n,
"/%s", log_file_name);
1473 PX4_INFO(
"Start file log (type: %s)",
log_type_str(type));
1478 PX4_ERR(
"failed to get log file name");
1537 PX4_INFO(
"Start mavlink log");
1559 PX4_INFO(
"Stop mavlink log");
1573 const int buffer_length = 220;
1574 char buffer[buffer_length];
1575 const char *perf_name;
1580 perf_name =
"perf_counter_preflight";
1583 perf_name =
"perf_counter_postflight";
1593 callback_data.
logger =
this;
1605 const char *perf_name;
1607 if (!callback_data->
buffer) {
1613 perf_name =
"perf_top_preflight";
1617 perf_name =
"perf_top_postflight";
1621 perf_name =
"perf_top_watchdog";
1625 perf_name =
"perf_top";
1637 callback_data.
logger =
this;
1639 callback_data.
buffer =
nullptr;
1652 PX4_ERR(
"Writing watchdog data");
1657 callback_data.
logger =
this;
1659 callback_data.
buffer = buffer;
1670 const int buffer_length = 220;
1671 char buffer[buffer_length];
1672 int size = px4_console_buffer_size();
1677 int read_size = px4_console_buffer_read(buffer, buffer_length - 1, &offset);
1679 if (read_size <= 0) {
break; }
1681 buffer[
math::min(read_size, size)] =
'\0';
1696 PX4_ERR(
"max recursion level reached (%i)", level);
1701 for (
const auto &written_format : written_formats) {
1702 if (written_format == &meta) {
1709 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
format) + format_len;
1714 if (!written_formats.push_back(&meta)) {
1715 PX4_ERR(
"Array too small");
1722 while (fmt && *fmt) {
1725 const char *space = strchr(fmt,
' ');
1728 PX4_ERR(
"invalid format %s", fmt);
1732 const char *array_start = strchr(fmt,
'[');
1736 if (array_start && array_start < space) {
1737 type_length = array_start - fmt;
1740 type_length = space - fmt;
1743 if (type_length >= (
int)
sizeof(type_name)) {
1744 PX4_ERR(
"buf len too small");
1748 memcpy(type_name, fmt, type_length);
1749 type_name[type_length] =
'\0';
1752 if (strcmp(type_name,
"int8_t") != 0 &&
1753 strcmp(type_name,
"uint8_t") != 0 &&
1754 strcmp(type_name,
"int16_t") != 0 &&
1755 strcmp(type_name,
"uint16_t") != 0 &&
1756 strcmp(type_name,
"int16_t") != 0 &&
1757 strcmp(type_name,
"uint16_t") != 0 &&
1758 strcmp(type_name,
"int32_t") != 0 &&
1759 strcmp(type_name,
"uint32_t") != 0 &&
1760 strcmp(type_name,
"int64_t") != 0 &&
1761 strcmp(type_name,
"uint64_t") != 0 &&
1762 strcmp(type_name,
"float") != 0 &&
1763 strcmp(type_name,
"double") != 0 &&
1764 strcmp(type_name,
"bool") != 0 &&
1765 strcmp(type_name,
"char") != 0) {
1772 if (strcmp(topics[i]->o_name, type_name) == 0) {
1773 found_topic = topics[i];
1779 write_format(type, *found_topic, written_formats, msg, level + 1);
1782 PX4_ERR(
"No definition for topic %s found", fmt);
1786 fmt = strchr(fmt,
';');
1807 for (
size_t i = 0; i < sub_count; ++i) {
1825 for (
size_t i = 0; i < sub_count; ++i) {
1843 PX4_ERR(
"limit for _next_topic_id reached");
1857 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
message_name) + message_name_len;
1870 uint8_t *buffer =
reinterpret_cast<uint8_t *
>(&
msg);
1874 size_t vlen = strlen(value);
1875 msg.
key_len = snprintf(msg.
key,
sizeof(msg.
key),
"char[%zu] %s", vlen, name);
1876 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
key) + msg.
key_len;
1879 if (vlen < (
sizeof(msg) - msg_size)) {
1880 memcpy(&buffer[msg_size], value, vlen);
1895 uint8_t *buffer =
reinterpret_cast<uint8_t *
>(&
msg);
1900 size_t vlen = strlen(value);
1901 msg.
key_len = snprintf(msg.
key,
sizeof(msg.
key),
"char[%zu] %s", vlen, name);
1902 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
key) + msg.
key_len;
1905 if (vlen < (
sizeof(msg) - msg_size)) {
1906 memcpy(&buffer[msg_size], value, vlen);
1914 PX4_ERR(
"info_multiple str too long (%i), key=%s", msg.
key_len, msg.
key);
1922 write_info_template<int32_t>(type,
name, value,
"int32_t");
1927 write_info_template<uint32_t>(type,
name, value,
"uint32_t");
1931 template<
typename T>
1936 uint8_t *buffer =
reinterpret_cast<uint8_t *
>(&
msg);
1940 msg.
key_len = snprintf(msg.
key,
sizeof(msg.
key),
"%s %s", type_str, name);
1941 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
key) + msg.
key_len;
1944 memcpy(&buffer[msg_size], &value,
sizeof(T));
1945 msg_size +=
sizeof(T);
1957 header.
magic[0] =
'U';
1958 header.
magic[1] =
'L';
1959 header.
magic[2] =
'o';
1960 header.
magic[3] =
'g';
1961 header.
magic[4] = 0x01;
1962 header.
magic[5] = 0x12;
1963 header.
magic[6] = 0x35;
1964 header.
magic[7] = 0x01;
1986 if (vendor_version > 0) {
1987 write_info(type,
"ver_vendor_sw_release", vendor_version);
1993 if (board_sub_type && board_sub_type[0]) {
1994 write_info(type,
"ver_hw_subtype", board_sub_type);
2003 if (git_branch && git_branch[0]) {
2004 write_info(type,
"ver_sw_branch", git_branch);
2017 if (ecl_version && ecl_version[0]) {
2018 write_info(type,
"sys_lib_ecl_ver", ecl_version);
2021 char revision =
'U';
2022 const char *chip_name =
nullptr;
2024 if (board_mcu_version(&revision, &chip_name,
nullptr) >= 0) {
2026 snprintf(mcu_ver,
sizeof(mcu_ver),
"%s, rev. %c", chip_name, revision);
2030 #ifndef BOARD_HAS_NO_UUID 2036 param_get(write_uuid_param, &write_uuid);
2038 if (write_uuid == 1) {
2039 char px4_uuid_string[PX4_GUID_FORMAT_SIZE];
2040 board_get_px4_guid_formated(px4_uuid_string,
sizeof(px4_uuid_string));
2041 write_info(type,
"sys_uuid", px4_uuid_string);
2047 int32_t utc_offset = 0;
2051 write_info(type,
"time_ref_utc", utc_offset * 60);
2067 uint8_t *buffer =
reinterpret_cast<uint8_t *
>(&
msg);
2083 const char *type_str;
2085 size_t value_size = 0;
2089 type_str =
"int32_t";
2090 value_size =
sizeof(int32_t);
2095 value_size =
sizeof(float);
2104 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
key) + msg.
key_len;
2109 param_get(param, (int32_t *)&buffer[msg_size]);
2113 param_get(param, (
float *)&buffer[msg_size]);
2120 msg_size += value_size;
2136 uint8_t *buffer =
reinterpret_cast<uint8_t *
>(&
msg);
2153 const char *type_str;
2155 size_t value_size = 0;
2159 type_str =
"int32_t";
2160 value_size =
sizeof(int32_t);
2165 value_size =
sizeof(float);
2174 size_t msg_size =
sizeof(
msg) -
sizeof(msg.
key) + msg.
key_len;
2179 param_get(param, (int32_t *)&buffer[msg_size]);
2183 param_get(param, (
float *)&buffer[msg_size]);
2190 msg_size += value_size;
2208 vehicle_command_ack.
result = (uint8_t)result;
2213 cmd_ack_pub.publish(vehicle_command_ack);
2219 PX4_WARN(
"%s\n", reason);
2222 PRINT_MODULE_DESCRIPTION(
2225 System logger which logs a configurable set of uORB topics and system printf messages 2226 (`PX4_WARN` and `PX4_ERR`) to ULog files. These can be used for system and flight performance evaluation, 2227 tuning, replay and crash analysis. 2229 It supports 2 backends: 2230 - Files: write ULog files to the file system (SD card) 2231 - MAVLink: stream ULog data via MAVLink to a client (the client must support this) 2233 Both backends can be enabled and used at the same time. 2235 The file backend supports 2 types of log files: full (the normal log) and a mission 2236 log. The mission log is a reduced ulog file and can be used for example for geotagging or 2237 vehicle management. It can be enabled and configured via SDLOG_MISSION parameter. 2238 The normal log is always a superset of the mission log. 2241 The implementation uses two threads: 2242 - The main thread, running at a fixed rate (or polling on a topic if started with -p) and checking for 2244 - The writer thread, writing data to the file 2246 In between there is a write buffer with configurable size (and another fixed-size buffer for 2247 the mission log). It should be large to avoid dropouts. 2250 Typical usage to start logging immediately: 2251 $ logger start -e -t 2253 Or if already running: 2257 PRINT_MODULE_USAGE_NAME("logger",
"system");
2258 PRINT_MODULE_USAGE_COMMAND(
"start");
2259 PRINT_MODULE_USAGE_PARAM_STRING(
'm',
"all",
"file|mavlink|all",
"Backend mode",
true);
2260 PRINT_MODULE_USAGE_PARAM_FLAG(
'x',
"Enable/disable logging via Aux1 RC channel",
true);
2261 PRINT_MODULE_USAGE_PARAM_FLAG(
'e',
"Enable logging right after start until disarm (otherwise only when armed)",
true);
2262 PRINT_MODULE_USAGE_PARAM_FLAG(
'f',
"Log until shutdown (implies -e)",
true);
2263 PRINT_MODULE_USAGE_PARAM_FLAG(
't',
"Use date/time for naming log directories and files",
true);
2264 PRINT_MODULE_USAGE_PARAM_INT(
'r', 280, 0, 8000,
"Log rate in Hz, 0 means unlimited rate",
true);
2265 PRINT_MODULE_USAGE_PARAM_INT(
'b', 12, 4, 10000,
"Log buffer size in KiB",
true);
2266 PRINT_MODULE_USAGE_PARAM_STRING(
'p',
nullptr,
"<topic_name>",
2267 "Poll on a topic instead of running with fixed rate (Log rate and topic intervals are ignored if this is set)",
true);
2268 PRINT_MODULE_USAGE_COMMAND_DESCR(
"on",
"start logging now, override arming (logger must be running)");
2269 PRINT_MODULE_USAGE_COMMAND_DESCR(
"off",
"stop logging now, override arming (logger must be running)");
2270 PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
#define mavlink_log_info(_pub, _text,...)
Send a mavlink info message (not printed to console).
bool write_message(LogType type, void *ptr, size_t size)
Write exactly one ulog message to the logger and handle dropouts.
#define PARAM_INVALID
Handle returned when a parameter cannot be found.
orb_advert_t _mavlink_log_pub
hrt_abstime dropout_start
start of current dropout (0 = no dropout)
void add_high_rate_topics()
void write_parameters(LogType type)
int perf_print_counter_buffer(char *buffer, int length, perf_counter_t handle)
Print one performance counter to a buffer.
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
LogFileName _file_name[(int) LogType::Count]
bool copy(void *dst)
Copy the struct.
__EXPORT bool param_value_unsaved(param_t param)
Test whether a parameter's value has been changed but not saved.
const char * px4_os_name(void)
name of the operating system
static void perf_iterate_callback(perf_counter_t handle, void *user)
callback to write the performance counters
const struct orb_metadata *const * orb_get_topics() __EXPORT
static const char * px4_board_sub_type(void)
get the board sub type
uint32_t px4_firmware_version(void)
get the PX4 Firmware version
uint8_t Backend
bitfield to specify a backend
Manages starting, stopping & writing of logged data using the configured backend. ...
const char * px4_toolchain_version(void)
Toolchain version used to compile PX4 (no particular format)
#define PARAM_TYPE_INT32
Parameter types.
bool update(void *dst)
Copy the struct if updated.
char log_dir[12]
e.g. "2018-01-01" or "sess001"
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
PrintLoadReason _print_load_reason
volatile bool watchdog_triggered
void write_info(LogType type, const char *name, const char *value)
print_load_s _load
process load data
const orb_metadata * _polling_topic_meta
if non-null, poll on this topic instead of sleeping
unsigned min_delta_ms
minimum time between 2 topic writes [ms]
void write_header(LogType type)
write the file header with file magic and timestamp.
void write_changed_parameters(LogType type)
uint8_t _next_topic_id
id of next subscribed ulog topic
static constexpr uint8_t MSG_ID_INVALID
const bool _log_name_timestamp
void initialize_load_output(PrintLoadReason reason)
initialize the output for the process load, so that ~1 second later it will be written to the log ...
void thread_stop()
stop all running threads and wait for them to exit
LogType
Defines different log (file) types.
int main(int argc, char **argv)
char log_file_name[31]
e.g. "log001.ulg" or "12_09_00_replayed.ulg"
void ack_vehicle_command(vehicle_command_s *cmd, uint32_t result)
bool _manually_logging_override
bool copy_if_updated(int sub_idx, void *buffer, bool try_to_subscribe)
pthread_t thread_id_file() const
reduced mission log (e.g. for geotagging)
static constexpr Backend BackendFile
void start_log_file(LogType type)
bool _should_stop_file_log
if true _next_load_print is set and file logging will be stopped after load printing (for the full lo...
bool add_topic(const char *name, uint32_t interval_ms=0, uint8_t instance=0)
Add a topic to be logged.
size_t high_water
maximum used write buffer
static int print_usage(const char *reason=nullptr)
void add_sensor_comparison_topics()
__EXPORT param_t param_for_index(unsigned index)
Look up a parameter by index.
void perf_reset_all(void)
Reset all of the performance counters.
Statistics _statistics[(int) LogType::Count]
static Logger * instantiate(int argc, char *argv[])
int write_message(LogType type, void *ptr, size_t size, uint64_t dropout_start=0)
Write a single ulog message (including header).
void watchdog_initialize(const pid_t pid_logger_main, const pthread_t writer_thread, watchdog_data_t &watchdog_data)
Initialize the watchdog, fill in watchdog_data.
bool need_reliable_transfer() const
void write_console_output()
write bootup console output
const char * px4_firmware_git_branch(void)
get the git branch name (can be empty, for example if HEAD points to a tag)
void start_log_file(LogType type, const char *filename)
Limiting / constrain helper functions.
bool watchdog_update(watchdog_data_t &watchdog_data)
Update the watchdog and trigger it if necessary.
static void print_usage()
void write_perf_data(bool preflight)
write performance counters
void init_print_load_s(uint64_t t, struct print_load_s *s)
const char * px4_toolchain_name(void)
Toolchain name used to compile PX4.
void add_thermal_calibration_topics()
void write_format(LogType type, const orb_metadata &meta, WrittenFormats &written_formats, ulog_message_format_s &msg, int level=1)
bool is_started(LogType type) const
whether logging is currently active or not (any of the selected backends).
__EXPORT unsigned param_count(void)
Return the total number of parameters.
uORB::Subscription _vehicle_status_sub
High-resolution timer with callouts and timekeeping.
void add_estimator_replay_topics()
void write_add_logged_msg(LogType type, LoggerSubscription &subscription)
Write an ADD_LOGGED_MSG to the log for a given subscription and instance.
int add_topics_from_file(const char *fname)
Parse a file containing a list of uORB topics to log, calling add_topic for each. ...
void stop_log_file(LogType type)
void write_load_output()
write the process load, which was previously initialized with initialize_load_output() ...
uORB::Subscription _vehicle_command_sub
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
static void print_load_callback(void *user)
callback for print_load_buffer() to print the process load
int orb_subscribe(const struct orb_metadata *meta)
void setReplayFile(const char *file_name)
Tell the logger that we're in replay mode.
static void timer_callback(void *arg)
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
uint32_t px4_os_version(void)
operating system version
__EXPORT const char * param_name(param_t param)
Obtain the name of a parameter.
void add_vision_and_avoidance_topics()
void add_default_topics()
static constexpr const char * LOG_ROOT[(int) LogType::Count]
Array< LoggerSubscription, MAX_TOPICS_NUM > _subscriptions
all subscriptions for full & mission log (in front)
bool get_log_time(struct tm *tt, int utc_offset_sec, bool boot_time)
Get the time for log file name.
bool can_start_mavlink_log() const
check if mavlink logging can be started
hrt_abstime _next_load_print
timestamp when to print the process load
void write_version(LogType type)
int orb_unsubscribe(int handle)
void stop_log_file(LogType type)
static struct actuator_armed_s armed
int logger_main(int argc, char *argv[])
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
void initialize_configured_topics()
Add topic subscriptions based on the _sdlog_profile_handle parameter.
void initialize_mission_topics(MissionLogType type)
Add topic subscriptions based on the configured mission log type.
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
#define ULOG_MSG_HEADER_LEN
uORB::Subscription _manual_control_sp_sub
__EXPORT param_type_t param_type(param_t param)
Obtain the type of a parameter.
static bool request_stop_static()
request the logger thread to stop (this method does not block).
__EXPORT void hrt_call_every(struct hrt_call *entry, hrt_abstime delay, hrt_abstime interval, hrt_callout callout, void *arg)
Call callout(arg) after delay, and then after every interval.
bool updated()
Check if there is a new update.
static constexpr Backend BackendAll
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
hrt_abstime start_time_file
Time when logging started, file backend (not the logger thread)
void add_system_identification_topics()
MissionSubscription _mission_subscriptions[MAX_MISSION_TOPICS_NUM]
additional data for mission subscriptions
static __BEGIN_DECLS const char * px4_board_name(void)
get the board name as string (including the version if there are multiple)
constexpr _Tp min(_Tp a, _Tp b)
const char * px4_firmware_version_string(void)
Firmware version as human readable string (git tag)
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Tools for system version detection.
size_t get_buffer_fill_count_file(LogType type) const
void select_write_backend(Backend sel_backend)
Select a backend, so that future calls to write_message() only write to the selected sel_backend...
void perf_iterate_all(perf_callback cb, void *user)
Iterate over all performance counters using a callback.
int sess_dir_index
search starting index for 'sess' directory name
int check_free_space(const char *log_root_dir, int32_t max_log_dirs_to_keep, orb_advert_t &mavlink_log_pub, int &sess_dir_index)
Check if there is enough free space left on the SD Card.
static int task_spawn(int argc, char *argv[])
bool add_topic_multi(const char *name, uint32_t interval_ms=0)
void write_info_multiple(LogType type, const char *name, const char *value, bool is_continued)
uint32_t px4_firmware_vendor_version(void)
get the PX4 Firmware vendor version
void print_load_buffer(uint64_t t, char *buffer, int buffer_length, print_load_callback_f cb, void *user, struct print_load_s *print_state)
Print load to a buffer, and call cb after each written line (buffer will not include ' ') ...
uORB::SubscriptionInterval _log_message_sub
void add_mission_topic(const char *name, uint32_t interval_ms=0)
Add a topic to be logged for the mission log (it's also added to the full log).
const char * configured_backend_mode() const
get the configured backend as string
void set_need_reliable_transfer(bool need_reliable)
Indicate to the underlying backend whether future write_message() calls need a reliable transfer...
#define ORB_MULTI_MAX_INSTANCES
Maximum number of multi topic instances.
void write_all_add_logged_msg(LogType type)
Write an ADD_LOGGED_MSG to the log for a all current subscriptions and instances. ...
int orb_unadvertise(orb_advert_t handle)
size_t write_dropouts
failed buffer writes due to buffer overflow
void debug_print_buffer(uint32_t &total_bytes, hrt_abstime &timer_start)
Regularly print the buffer fill state (only if DBGPRINT is set)
uint8_t get_instance() const
static constexpr hrt_abstime TRY_SUBSCRIBE_INTERVAL
unsigned next_write_time
next time to write in 0.1 seconds
param_t _sdlog_profile_handle
hrt_abstime _last_sync_time
last time a sync msg was sent
watchdog_data_t watchdog_data
bool _prev_state
previous state depending on logging mode (arming or aux1 state)
static constexpr int MAX_MISSION_TOPICS_NUM
Maximum number of mission topics.
bool update(void *dst)
Update the struct.
void write_formats(LogType type)
int print_status() override
void print_statistics(LogType type)
size_t orb_topics_count() __EXPORT
bool start_stop_logging(MissionLogType mission_log_type)
check current arming state or aux channel and start/stop logging if state changed and according to co...
float max_dropout_duration
max duration of dropout [s]
static constexpr Backend BackendMavlink
void write_info_template(LogType type, const char *name, T value, const char *type_str)
generic common template method for write_info variants
static int custom_command(int argc, char *argv[])
const char * px4_os_version_string(void)
Operating system version as human readable string (git tag)
bool file_exist(const char *filename)
check if a file exists
bool copy(void *dst)
Copy the struct.
orb_id_t get_topic() const
int create_log_dir(LogType type, tm *tt, char *log_dir, int log_dir_len)
Create logging directory.
int get_log_file_name(LogType type, char *file_name, size_t file_name_size)
Get log file name with directory (create it if necessary)
const char * log_type_str(LogType type)
Logger(LogWriter::Backend backend, size_t buffer_size, uint32_t log_interval, const char *poll_topic_name, LogMode log_mode, bool log_name_timestamp)
void unselect_write_backend()
const char * px4_ecl_lib_version_string(void)
ECL lib version as human readable string (git tag)
void handle_vehicle_command_update()
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
uint32_t param_t
Parameter handle.
__EXPORT void hrt_cancel(struct hrt_call *entry)
Remove the entry from the callout list.
static constexpr unsigned MAX_NO_LOGFILE
Maximum number of log files.
__EXPORT bool param_used(param_t param)
Wether a parameter is in use in the system.