diff --git a/Tools/Replay/DataFlashFileReader.cpp b/Tools/Replay/DataFlashFileReader.cpp index 8f1692bc11c..db40fd5e77a 100644 --- a/Tools/Replay/DataFlashFileReader.cpp +++ b/Tools/Replay/DataFlashFileReader.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,11 @@ bool AP_LoggerFileReader::open_log(const char *logfile) if (fd == -1) { return false; } + // Get the file size for percentage calculation + struct stat st; + if (AP::FS().stat(logfile, &st) == 0) { + file_size = st.st_size; + } return true; } @@ -100,3 +106,11 @@ bool AP_LoggerFileReader::update() message_count++; return handle_msg(f, msg); } + +float AP_LoggerFileReader::get_percent_read() +{ + if (file_size == 0) { + return 0.0f; + } + return (float)(bytes_read * 100.0 / file_size); +} diff --git a/Tools/Replay/DataFlashFileReader.h b/Tools/Replay/DataFlashFileReader.h index b03e077ac4d..2c78a0a08c5 100644 --- a/Tools/Replay/DataFlashFileReader.h +++ b/Tools/Replay/DataFlashFileReader.h @@ -19,6 +19,7 @@ public: void format_type(uint16_t type, char dest[5]); void get_packet_counts(uint64_t dest[]); + float get_percent_read(); // Get percentage of log file read protected: int fd = -1; @@ -29,6 +30,7 @@ private: ssize_t read_input(void *buf, size_t count); uint64_t bytes_read = 0; + uint64_t file_size = 0; // Total size of the log file uint32_t message_count = 0; uint64_t start_micros; diff --git a/Tools/Replay/Replay.cpp b/Tools/Replay/Replay.cpp index 2123fceb7e0..2c2bc5d5595 100644 --- a/Tools/Replay/Replay.cpp +++ b/Tools/Replay/Replay.cpp @@ -39,6 +39,7 @@ static ReplayVehicle replayvehicle; user_parameter *user_parameters; bool replay_force_ekf2; bool replay_force_ekf3; +bool show_progress; const AP_Param::Info ReplayVehicle::var_info[] = { GSCALAR(dummy, "_DUMMY", 0), @@ -127,6 +128,7 @@ void Replay::usage(void) ::printf("\t--param-file FILENAME load parameters from a file\n"); ::printf("\t--force-ekf2 force enable EKF2\n"); ::printf("\t--force-ekf3 force enable EKF3\n"); + ::printf("\t--progress show a progress bar during replay\n"); } enum param_key : uint8_t { @@ -143,11 +145,12 @@ void Replay::_parse_command_line(uint8_t argc, char * const argv[]) {"param-file", true, 0, 'F'}, {"force-ekf2", false, 0, param_key::FORCE_EKF2}, {"force-ekf3", false, 0, param_key::FORCE_EKF3}, + {"progress", false, 0, 'P'}, {"help", false, 0, 'h'}, {0, false, 0, 0} }; - GetOptLong gopt(argc, argv, "p:F:h", options); + GetOptLong gopt(argc, argv, "p:F:Ph", options); int opt; while ((opt = gopt.getoption()) != -1) { @@ -177,6 +180,10 @@ void Replay::_parse_command_line(uint8_t argc, char * const argv[]) case param_key::FORCE_EKF3: replay_force_ekf3 = true; break; + + case 'P': + show_progress = true; + break; case 'h': default: @@ -300,6 +307,35 @@ void Replay::loop() #endif exit(0); } + + // Display progress bar if enabled + if (show_progress) { + uint32_t now = AP_HAL::millis(); + if (now - last_progress_update > 100) { // Update every 100ms + last_progress_update = now; + float percent = reader.get_percent_read(); + + // Create a 50-character progress bar + const uint8_t bar_width = 50; + uint8_t completed_chars = (uint8_t)(percent * bar_width / 100.0f); + + // Print the progress bar + printf("\rProgress: ["); + for (uint8_t i = 0; i < bar_width; i++) { + if (i < completed_chars) { + printf("="); + } else if (i == completed_chars) { + printf(">"); + } else { + printf(" "); + } + } + printf("] %.1f%%", percent); + if (percent >= 100.0f) { + printf("\n"); + } + } + } } /* diff --git a/Tools/Replay/Replay.h b/Tools/Replay/Replay.h index aa628d1856f..cc32d367bc4 100644 --- a/Tools/Replay/Replay.h +++ b/Tools/Replay/Replay.h @@ -100,6 +100,8 @@ private: ReplayVehicle &_vehicle; LogReader reader{_vehicle.log_structure, _vehicle.ekf2, _vehicle.ekf3}; + bool show_progress = false; // Flag to determine if progress bar should be shown + uint32_t last_progress_update = 0; // Last time progress was displayed void _parse_command_line(uint8_t argc, char * const argv[]);