blob: 63c3de46eff06c62471e1eee94ddd0e5c328280f [file] [log] [blame]
Austin Schuh59d93f42022-07-18 16:52:32 -07001#include "absl/strings/str_cat.h"
2#include "absl/strings/str_split.h"
3#include "aos/init.h"
4#include "aos/util/file.h"
5#include "frc971/analysis/in_process_plotter.h"
6
7using frc971::analysis::Plotter;
8
9// Simple C++ application to read the CSV files and use the in process plotter
10// to plot them. This smokes the pants off gnuplot in terms of interactivity.
11
12namespace aos {
13
14std::pair<std::vector<double>, std::vector<double>> ReadSamples(
15 std::string_view node1, std::string_view node2, bool flip) {
16 std::vector<double> samplefile12_t;
17 std::vector<double> samplefile12_o;
18
19 const std::string file = aos::util::ReadFileToStringOrDie(absl::StrCat(
20 "/tmp/timestamp_noncausal_", node1, "_", node2, "_samples.csv"));
21 bool first = true;
22 std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
23 samplefile12_t.reserve(lines.size());
24 for (const std::string_view n : lines) {
25 if (first) {
26 first = false;
27 continue;
28 }
29 if (n == "") {
30 continue;
31 }
32
33 std::vector<std::string_view> l = absl::StrSplit(n, ", ");
34 CHECK_EQ(l.size(), 4u);
35 double t;
36 double o;
37 CHECK(absl::SimpleAtod(l[0], &t));
38 CHECK(absl::SimpleAtod(l[1], &o));
39 samplefile12_t.emplace_back(t);
40 samplefile12_o.emplace_back(flip ? -o : o);
41 }
42 return std::make_pair(samplefile12_t, samplefile12_o);
43}
44
45std::pair<std::vector<double>, std::vector<double>> ReadLines(
46 std::string_view node1, std::string_view node2, bool flip) {
47 std::vector<double> samplefile12_t;
48 std::vector<double> samplefile12_o;
49
50 const std::string file = aos::util::ReadFileToStringOrDie(
51 absl::StrCat("/tmp/timestamp_noncausal_", node1, "_", node2, ".csv"));
52 bool first = true;
53 std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
54 samplefile12_t.reserve(lines.size());
55 for (const std::string_view n : lines) {
56 if (first) {
57 first = false;
58 continue;
59 }
60 if (n == "") {
61 continue;
62 }
63
64 std::vector<std::string_view> l = absl::StrSplit(n, ", ");
65 CHECK_EQ(l.size(), 3u);
66 double t;
67 double o;
68 CHECK(absl::SimpleAtod(l[0], &t));
69 CHECK(absl::SimpleAtod(l[2], &o));
70 samplefile12_t.emplace_back(t);
71 samplefile12_o.emplace_back(flip ? -o : o);
72 }
73 return std::make_pair(samplefile12_t, samplefile12_o);
74}
75
76std::pair<std::vector<double>, std::vector<double>> ReadOffset(
77 std::string_view node1, std::string_view node2) {
78 int node1_index = -1;
79 int node2_index = -1;
80
81 {
82 const std::string start_time_file = aos::util::ReadFileToStringOrDie(
83 "/tmp/timestamp_noncausal_starttime.csv");
84 std::vector<std::string_view> nodes = absl::StrSplit(start_time_file, '\n');
85
86 int index = 0;
87 for (const std::string_view n : nodes) {
88 if (n == "") {
89 continue;
90 }
91
92 std::vector<std::string_view> l = absl::StrSplit(n, ", ");
93 CHECK_EQ(l.size(), 2u) << "'" << n << "'";
94 if (l[0] == node1) {
95 node1_index = index;
96 }
97 if (l[0] == node2) {
98 node2_index = index;
99 }
100 ++index;
101 }
102 }
103 CHECK_NE(node1_index, -1) << ": Unknown node " << node1;
104 CHECK_NE(node2_index, -1) << ": Unknown node " << node2;
105 std::vector<double> offsetfile_t;
106 std::vector<double> offsetfile_o;
107
108 const std::string file =
109 aos::util::ReadFileToStringOrDie("/tmp/timestamp_noncausal_offsets.csv");
110 bool first = true;
111 std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
112 offsetfile_t.reserve(lines.size());
113 for (const std::string_view n : lines) {
114 if (first) {
115 first = false;
116 continue;
117 }
118 if (n == "") {
119 continue;
120 }
121
122 std::vector<std::string_view> l = absl::StrSplit(n, ", ");
123 CHECK_LT(static_cast<size_t>(node1_index + 1), l.size());
124 CHECK_LT(static_cast<size_t>(node2_index + 1), l.size());
125 double t;
126 double o1;
127 double o2;
128 CHECK(absl::SimpleAtod(l[0], &t));
129 CHECK(absl::SimpleAtod(l[1 + node1_index], &o1));
130 CHECK(absl::SimpleAtod(l[1 + node2_index], &o2));
131 offsetfile_t.emplace_back(t);
132 offsetfile_o.emplace_back(o2 - o1);
133 }
134 return std::make_pair(offsetfile_t, offsetfile_o);
135}
136
137void AddNodes(Plotter *plotter, std::string_view node1,
138 std::string_view node2) {
139 const std::pair<std::vector<double>, std::vector<double>> samplefile12 =
140 ReadSamples(node1, node2, false);
141 const std::pair<std::vector<double>, std::vector<double>> samplefile21 =
142 ReadSamples(node2, node1, true);
143
144 const std::pair<std::vector<double>, std::vector<double>> noncausalfile12 =
145 ReadLines(node1, node2, false);
146 const std::pair<std::vector<double>, std::vector<double>> noncausalfile21 =
147 ReadLines(node2, node1, true);
148
149 const std::pair<std::vector<double>, std::vector<double>> offsetfile =
150 ReadOffset(node1, node2);
151
152 CHECK_EQ(samplefile12.first.size(), samplefile12.second.size());
153 CHECK_EQ(samplefile21.first.size(), samplefile21.second.size());
154 CHECK_EQ(noncausalfile12.first.size(), noncausalfile12.second.size());
155 CHECK_EQ(noncausalfile21.first.size(), noncausalfile21.second.size());
156
157 LOG(INFO) << samplefile12.first.size() + samplefile21.first.size() +
158 noncausalfile12.first.size() + noncausalfile21.first.size()
159 << " points";
160 plotter->AddLine(
161 samplefile12.first, samplefile12.second,
162 Plotter::LineOptions{.label = absl::StrCat("sample ", node1, " ", node2),
163 .line_style = "*",
164 .color = "purple"});
165 plotter->AddLine(
166 samplefile21.first, samplefile21.second,
167 Plotter::LineOptions{.label = absl::StrCat("sample ", node2, " ", node1),
168 .line_style = "*",
169 .color = "green"});
170
171 plotter->AddLine(
172 noncausalfile12.first, noncausalfile12.second,
173 Plotter::LineOptions{.label = absl::StrCat("nc ", node1, " ", node2),
174 .line_style = "-",
175 .color = "blue"});
176 plotter->AddLine(
177 noncausalfile21.first, noncausalfile21.second,
178 Plotter::LineOptions{.label = absl::StrCat("nc ", node2, " ", node1),
179 .line_style = "-",
180 .color = "orange"});
181
182 plotter->AddLine(offsetfile.first, offsetfile.second,
183 Plotter::LineOptions{
184 .label = absl::StrCat("filter ", node2, " ", node1),
185 // TODO(austin): roboRIO compiler wants all the fields
186 // filled out, but other compilers don't... Sigh.
187 .line_style = "*-",
188 .color = "yellow"});
189}
190
191int Main(int argc, const char *const *argv) {
192 CHECK_EQ(argc, 3);
193
194 LOG(INFO) << argv[1];
195 LOG(INFO) << argv[2];
196
197 // TODO(austin): Find all node pairs and plot them...
198
199 const std::string_view node1 = argv[1];
200 const std::string_view node2 = argv[2];
201
202 Plotter plotter;
203 plotter.AddFigure("Time");
204
205 AddNodes(&plotter, node1, node2);
206
207 plotter.Publish();
208
209 plotter.Spin();
210
211 return 0;
212}
213
214} // namespace aos
215
216int main(int argc, char **argv) {
217 aos::InitGoogle(&argc, &argv);
218
219 aos::Main(argc, argv);
220}