blob: 63c3de46eff06c62471e1eee94ddd0e5c328280f [file] [log] [blame]
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "aos/init.h"
#include "aos/util/file.h"
#include "frc971/analysis/in_process_plotter.h"
using frc971::analysis::Plotter;
// Simple C++ application to read the CSV files and use the in process plotter
// to plot them. This smokes the pants off gnuplot in terms of interactivity.
namespace aos {
std::pair<std::vector<double>, std::vector<double>> ReadSamples(
std::string_view node1, std::string_view node2, bool flip) {
std::vector<double> samplefile12_t;
std::vector<double> samplefile12_o;
const std::string file = aos::util::ReadFileToStringOrDie(absl::StrCat(
"/tmp/timestamp_noncausal_", node1, "_", node2, "_samples.csv"));
bool first = true;
std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
samplefile12_t.reserve(lines.size());
for (const std::string_view n : lines) {
if (first) {
first = false;
continue;
}
if (n == "") {
continue;
}
std::vector<std::string_view> l = absl::StrSplit(n, ", ");
CHECK_EQ(l.size(), 4u);
double t;
double o;
CHECK(absl::SimpleAtod(l[0], &t));
CHECK(absl::SimpleAtod(l[1], &o));
samplefile12_t.emplace_back(t);
samplefile12_o.emplace_back(flip ? -o : o);
}
return std::make_pair(samplefile12_t, samplefile12_o);
}
std::pair<std::vector<double>, std::vector<double>> ReadLines(
std::string_view node1, std::string_view node2, bool flip) {
std::vector<double> samplefile12_t;
std::vector<double> samplefile12_o;
const std::string file = aos::util::ReadFileToStringOrDie(
absl::StrCat("/tmp/timestamp_noncausal_", node1, "_", node2, ".csv"));
bool first = true;
std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
samplefile12_t.reserve(lines.size());
for (const std::string_view n : lines) {
if (first) {
first = false;
continue;
}
if (n == "") {
continue;
}
std::vector<std::string_view> l = absl::StrSplit(n, ", ");
CHECK_EQ(l.size(), 3u);
double t;
double o;
CHECK(absl::SimpleAtod(l[0], &t));
CHECK(absl::SimpleAtod(l[2], &o));
samplefile12_t.emplace_back(t);
samplefile12_o.emplace_back(flip ? -o : o);
}
return std::make_pair(samplefile12_t, samplefile12_o);
}
std::pair<std::vector<double>, std::vector<double>> ReadOffset(
std::string_view node1, std::string_view node2) {
int node1_index = -1;
int node2_index = -1;
{
const std::string start_time_file = aos::util::ReadFileToStringOrDie(
"/tmp/timestamp_noncausal_starttime.csv");
std::vector<std::string_view> nodes = absl::StrSplit(start_time_file, '\n');
int index = 0;
for (const std::string_view n : nodes) {
if (n == "") {
continue;
}
std::vector<std::string_view> l = absl::StrSplit(n, ", ");
CHECK_EQ(l.size(), 2u) << "'" << n << "'";
if (l[0] == node1) {
node1_index = index;
}
if (l[0] == node2) {
node2_index = index;
}
++index;
}
}
CHECK_NE(node1_index, -1) << ": Unknown node " << node1;
CHECK_NE(node2_index, -1) << ": Unknown node " << node2;
std::vector<double> offsetfile_t;
std::vector<double> offsetfile_o;
const std::string file =
aos::util::ReadFileToStringOrDie("/tmp/timestamp_noncausal_offsets.csv");
bool first = true;
std::vector<std::string_view> lines = absl::StrSplit(file, '\n');
offsetfile_t.reserve(lines.size());
for (const std::string_view n : lines) {
if (first) {
first = false;
continue;
}
if (n == "") {
continue;
}
std::vector<std::string_view> l = absl::StrSplit(n, ", ");
CHECK_LT(static_cast<size_t>(node1_index + 1), l.size());
CHECK_LT(static_cast<size_t>(node2_index + 1), l.size());
double t;
double o1;
double o2;
CHECK(absl::SimpleAtod(l[0], &t));
CHECK(absl::SimpleAtod(l[1 + node1_index], &o1));
CHECK(absl::SimpleAtod(l[1 + node2_index], &o2));
offsetfile_t.emplace_back(t);
offsetfile_o.emplace_back(o2 - o1);
}
return std::make_pair(offsetfile_t, offsetfile_o);
}
void AddNodes(Plotter *plotter, std::string_view node1,
std::string_view node2) {
const std::pair<std::vector<double>, std::vector<double>> samplefile12 =
ReadSamples(node1, node2, false);
const std::pair<std::vector<double>, std::vector<double>> samplefile21 =
ReadSamples(node2, node1, true);
const std::pair<std::vector<double>, std::vector<double>> noncausalfile12 =
ReadLines(node1, node2, false);
const std::pair<std::vector<double>, std::vector<double>> noncausalfile21 =
ReadLines(node2, node1, true);
const std::pair<std::vector<double>, std::vector<double>> offsetfile =
ReadOffset(node1, node2);
CHECK_EQ(samplefile12.first.size(), samplefile12.second.size());
CHECK_EQ(samplefile21.first.size(), samplefile21.second.size());
CHECK_EQ(noncausalfile12.first.size(), noncausalfile12.second.size());
CHECK_EQ(noncausalfile21.first.size(), noncausalfile21.second.size());
LOG(INFO) << samplefile12.first.size() + samplefile21.first.size() +
noncausalfile12.first.size() + noncausalfile21.first.size()
<< " points";
plotter->AddLine(
samplefile12.first, samplefile12.second,
Plotter::LineOptions{.label = absl::StrCat("sample ", node1, " ", node2),
.line_style = "*",
.color = "purple"});
plotter->AddLine(
samplefile21.first, samplefile21.second,
Plotter::LineOptions{.label = absl::StrCat("sample ", node2, " ", node1),
.line_style = "*",
.color = "green"});
plotter->AddLine(
noncausalfile12.first, noncausalfile12.second,
Plotter::LineOptions{.label = absl::StrCat("nc ", node1, " ", node2),
.line_style = "-",
.color = "blue"});
plotter->AddLine(
noncausalfile21.first, noncausalfile21.second,
Plotter::LineOptions{.label = absl::StrCat("nc ", node2, " ", node1),
.line_style = "-",
.color = "orange"});
plotter->AddLine(offsetfile.first, offsetfile.second,
Plotter::LineOptions{
.label = absl::StrCat("filter ", node2, " ", node1),
// TODO(austin): roboRIO compiler wants all the fields
// filled out, but other compilers don't... Sigh.
.line_style = "*-",
.color = "yellow"});
}
int Main(int argc, const char *const *argv) {
CHECK_EQ(argc, 3);
LOG(INFO) << argv[1];
LOG(INFO) << argv[2];
// TODO(austin): Find all node pairs and plot them...
const std::string_view node1 = argv[1];
const std::string_view node2 = argv[2];
Plotter plotter;
plotter.AddFigure("Time");
AddNodes(&plotter, node1, node2);
plotter.Publish();
plotter.Spin();
return 0;
}
} // namespace aos
int main(int argc, char **argv) {
aos::InitGoogle(&argc, &argv);
aos::Main(argc, argv);
}