blob: a92d74ed1acf4141e4289249fed7b8556474c45d [file] [log] [blame]
James Kuszmaul14d7ea12023-12-09 15:41:14 -08001#include <optional>
2
Austin Schuh99f7c6a2024-06-25 22:07:44 -07003#include "absl/flags/flag.h"
4#include "absl/flags/usage.h"
5#include "absl/log/check.h"
6#include "absl/log/log.h"
James Kuszmaul14d7ea12023-12-09 15:41:14 -08007
8#include "aos/events/logging/log_reader.h"
9#include "aos/init.h"
10#include "aos/util/simulation_logger.h"
11#include "frc971/input/joystick_state_generated.h"
12
Austin Schuh99f7c6a2024-06-25 22:07:44 -070013ABSL_FLAG(std::string, output_folder, "/tmp/trimmed/",
14 "Name of the folder to write the trimmed log to.");
15ABSL_FLAG(std::string, node, "roborio", "");
16ABSL_FLAG(bool, auto, false, "If set, trim the log to just the auto mode.");
17ABSL_FLAG(double, pre_enable_time_sec, 10.0,
18 "Amount of time to leave in the new log before the first enable "
19 "signal happens.");
20ABSL_FLAG(double, post_enable_time_sec, 1.0,
21 "Amount of time to leave in the new log after the final enable "
22 "signal ends.");
23ABSL_FLAG(double, force_start_monotonic, -1.0,
24 "If set, time, in seconds, at which to forcibly trim the start "
25 "of the log.");
26ABSL_FLAG(
27 double, force_end_monotonic, -1.0,
James Kuszmaulee525992024-03-15 21:01:16 -070028 "If set, time, in seconds, at which to forcibly trim the end of the log.");
James Kuszmaul14d7ea12023-12-09 15:41:14 -080029
30int main(int argc, char *argv[]) {
Austin Schuh99f7c6a2024-06-25 22:07:44 -070031 absl::SetProgramUsageMessage(
James Kuszmaul14d7ea12023-12-09 15:41:14 -080032 "Trims the sections at the start/end of a log where the robot is "
33 "disabled.");
34 aos::InitGoogle(&argc, &argv);
35 const std::vector<aos::logger::LogFile> logfiles =
36 aos::logger::SortParts(aos::logger::FindLogs(argc, argv));
37 std::optional<aos::monotonic_clock::time_point> start_time;
38 std::optional<aos::monotonic_clock::time_point> end_time;
39 bool printed_match = false;
Austin Schuh99f7c6a2024-06-25 22:07:44 -070040 bool force_time_range = absl::GetFlag(FLAGS_force_start_monotonic) > 0;
James Kuszmaul14d7ea12023-12-09 15:41:14 -080041 // We need to do two passes through the logfile; one to figure out when the
42 // start/end times are, one to actually do the trimming.
James Kuszmaulee525992024-03-15 21:01:16 -070043 if (!force_time_range) {
James Kuszmaul14d7ea12023-12-09 15:41:14 -080044 aos::logger::LogReader reader(logfiles);
Austin Schuh99f7c6a2024-06-25 22:07:44 -070045 const aos::Node *roborio = aos::configuration::GetNode(
46 reader.configuration(), absl::GetFlag(FLAGS_node));
James Kuszmaul14d7ea12023-12-09 15:41:14 -080047 reader.Register();
48 std::unique_ptr<aos::EventLoop> event_loop =
Austin Schuh99f7c6a2024-06-25 22:07:44 -070049 reader.event_loop_factory()->MakeEventLoop(absl::GetFlag(FLAGS_node),
50 roborio);
51 event_loop->MakeWatcher("/aos", [&start_time, &end_time, &printed_match,
52 &event_loop](
53 const aos::JoystickState &msg) {
54 if (!printed_match && msg.match_type() != aos::MatchType::kNone) {
55 LOG(INFO) << "Match Type: " << aos::EnumNameMatchType(msg.match_type());
56 LOG(INFO) << "Match #: " << msg.match_number();
57 printed_match = true;
58 }
James Kuszmaul14d7ea12023-12-09 15:41:14 -080059
Austin Schuh99f7c6a2024-06-25 22:07:44 -070060 if (msg.enabled() && (!absl::GetFlag(FLAGS_auto) || msg.autonomous())) {
61 // Note that time is monotonic, so we don't need to e.g. do min's or
62 // max's on the start/end time.
63 if (!start_time.has_value()) {
64 start_time = event_loop->context().monotonic_event_time;
65 }
66 end_time = event_loop->context().monotonic_event_time;
67 }
68 });
James Kuszmaul14d7ea12023-12-09 15:41:14 -080069
70 reader.event_loop_factory()->Run();
71
72 if (!printed_match) {
73 LOG(INFO) << "No match info.";
74 }
James Kuszmaulee525992024-03-15 21:01:16 -070075 if (!start_time.has_value()) {
76 LOG(WARNING) << "Log does not ontain any JoystickState messages.";
77 return 1;
78 }
79 LOG(INFO) << "First enable at " << start_time.value();
80 LOG(INFO) << "Final enable at " << end_time.value();
81 start_time.value() -= std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh99f7c6a2024-06-25 22:07:44 -070082 std::chrono::duration<double>(
83 absl::GetFlag(FLAGS_pre_enable_time_sec)));
James Kuszmaulee525992024-03-15 21:01:16 -070084 end_time.value() += std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh99f7c6a2024-06-25 22:07:44 -070085 std::chrono::duration<double>(
86 absl::GetFlag(FLAGS_post_enable_time_sec)));
James Kuszmaulee525992024-03-15 21:01:16 -070087 } else {
Austin Schuh99f7c6a2024-06-25 22:07:44 -070088 CHECK_LT(absl::GetFlag(FLAGS_force_start_monotonic),
89 absl::GetFlag(FLAGS_force_end_monotonic));
James Kuszmaulee525992024-03-15 21:01:16 -070090 start_time = aos::monotonic_clock::time_point(
91 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh99f7c6a2024-06-25 22:07:44 -070092 std::chrono::duration<double>(
93 absl::GetFlag(FLAGS_force_start_monotonic))));
James Kuszmaulee525992024-03-15 21:01:16 -070094 end_time = aos::monotonic_clock::time_point(
95 std::chrono::duration_cast<std::chrono::nanoseconds>(
Austin Schuh99f7c6a2024-06-25 22:07:44 -070096 std::chrono::duration<double>(
97 absl::GetFlag(FLAGS_force_end_monotonic))));
James Kuszmaul14d7ea12023-12-09 15:41:14 -080098 }
James Kuszmaul14d7ea12023-12-09 15:41:14 -080099
100 {
101 aos::logger::LogReader reader(logfiles);
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700102 const aos::Node *roborio = aos::configuration::GetNode(
103 reader.configuration(), absl::GetFlag(FLAGS_node));
James Kuszmaul14d7ea12023-12-09 15:41:14 -0800104 reader.Register();
105 std::unique_ptr<aos::EventLoop> event_loop =
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700106 reader.event_loop_factory()->MakeEventLoop(absl::GetFlag(FLAGS_node),
107 roborio);
James Kuszmaul14d7ea12023-12-09 15:41:14 -0800108 auto exit_timer = event_loop->AddTimer(
109 [&reader]() { reader.event_loop_factory()->Exit(); });
110 exit_timer->Schedule(start_time.value());
111 reader.event_loop_factory()->Run();
112 const std::set<std::string> logger_nodes =
113 aos::logger::LoggerNodes(logfiles);
114 // Only start up loggers that generated the original set of logfiles.
115 // This mostly exists to make it so that utilities like log_to_mcap can
116 // easily auto-detect which node to replay as when consuming the input logs.
117 auto loggers = aos::util::MakeLoggersForNodes(
118 reader.event_loop_factory(), {logger_nodes.begin(), logger_nodes.end()},
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700119 absl::GetFlag(FLAGS_output_folder));
James Kuszmaul14d7ea12023-12-09 15:41:14 -0800120 exit_timer->Schedule(end_time.value());
121
122 reader.event_loop_factory()->Run();
123 }
124
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700125 LOG(INFO) << "Trimmed logs written to " << absl::GetFlag(FLAGS_output_folder);
James Kuszmaul14d7ea12023-12-09 15:41:14 -0800126
127 return EXIT_SUCCESS;
128}