blob: f345ebcf590e9836fce88b9d71c9054d9d6ea3c5 [file] [log] [blame]
James Kuszmaul48671362020-12-24 13:54:16 -08001#include "frc971/analysis/in_process_plotter.h"
2
3#include "aos/configuration.h"
4
5namespace frc971 {
6namespace analysis {
7
8namespace {
9const char *kDataPath = "frc971/analysis";
10const char *kConfigPath = "frc971/analysis/plotter.json";
11} // namespace
12
13Plotter::Plotter()
14 : config_(aos::configuration::ReadConfig(kConfigPath)),
15 event_loop_factory_(&config_.message()),
16 event_loop_(event_loop_factory_.MakeEventLoop("plotter")),
17 plot_sender_(event_loop_->MakeSender<Plot>("/analysis")),
James Kuszmaul1a29c082022-02-03 14:02:47 -080018 web_proxy_(event_loop_.get(), aos::web_proxy::StoreHistory::kYes, -1),
James Kuszmaul48671362020-12-24 13:54:16 -080019 builder_(plot_sender_.MakeBuilder()) {
20 web_proxy_.SetDataPath(kDataPath);
21 event_loop_->SkipTimingReport();
22 color_wheel_.push_back(Color(1, 0, 0));
23 color_wheel_.push_back(Color(0, 1, 0));
24 color_wheel_.push_back(Color(0, 0, 1));
25 color_wheel_.push_back(Color(1, 1, 0));
26 color_wheel_.push_back(Color(0, 1, 1));
27 color_wheel_.push_back(Color(1, 0, 1));
Austin Schuhc2e9c502021-11-25 21:23:24 -080028 color_wheel_.push_back(Color(1, 0.6, 0));
29 color_wheel_.push_back(Color(0.6, 0.3, 0));
30 color_wheel_.push_back(Color(1, 1, 1));
James Kuszmaul48671362020-12-24 13:54:16 -080031}
32
33void Plotter::Spin() { event_loop_factory_.Run(); }
34
35void Plotter::Title(std::string_view title) {
36 title_ = builder_.fbb()->CreateString(title);
37}
38
39void Plotter::AddFigure(std::string_view title, double width, double height) {
40 MaybeFinishFigure();
41
42 if (!title.empty()) {
43 figure_title_ = builder_.fbb()->CreateString(title);
44 }
45
46 // For positioning, just stack figures vertically.
47 auto position_builder = builder_.MakeBuilder<Position>();
48 position_builder.add_top(next_top_);
49 position_builder.add_left(0);
50 position_builder.add_width(width);
51 position_builder.add_height(height);
52 position_ = position_builder.Finish();
53
54 next_top_ += height;
55}
56
57void Plotter::XLabel(std::string_view label) {
58 xlabel_ = builder_.fbb()->CreateString(label);
59}
60
61void Plotter::YLabel(std::string_view label) {
62 ylabel_ = builder_.fbb()->CreateString(label);
63}
64
65void Plotter::AddLine(const std::vector<double> &x,
James Kuszmaul19217a42022-06-17 10:54:29 -070066 const std::vector<double> &y, std::string_view label,
67 std::string_view line_style) {
James Kuszmaul48671362020-12-24 13:54:16 -080068 CHECK_EQ(x.size(), y.size());
69 CHECK(!position_.IsNull())
70 << "You must call AddFigure() before calling AddLine().";
71
72 flatbuffers::Offset<flatbuffers::String> label_offset;
73 if (!label.empty()) {
74 label_offset = builder_.fbb()->CreateString(label);
75 }
76
77 std::vector<Point> points;
78 for (size_t ii = 0; ii < x.size(); ++ii) {
79 points.emplace_back(x[ii], y[ii]);
80 }
milind1f1dca32021-07-03 13:50:07 -070081 const flatbuffers::Offset<flatbuffers::Vector<const Point *>> points_offset =
82 builder_.fbb()->CreateVectorOfStructs(points);
James Kuszmaul48671362020-12-24 13:54:16 -080083
84 const Color *color = &color_wheel_.at(color_wheel_position_);
85 color_wheel_position_ = (color_wheel_position_ + 1) % color_wheel_.size();
86
James Kuszmaul19217a42022-06-17 10:54:29 -070087 LineStyle::Builder style_builder = builder_.MakeBuilder<LineStyle>();
88 if (line_style.find('*') != line_style.npos) {
89 style_builder.add_point_size(3.0);
90 } else {
91 style_builder.add_point_size(0.0);
92 }
93 style_builder.add_draw_line(line_style.find('-') != line_style.npos);
94 const flatbuffers::Offset<LineStyle> style_offset = style_builder.Finish();
95
James Kuszmaul48671362020-12-24 13:54:16 -080096 auto line_builder = builder_.MakeBuilder<Line>();
97 line_builder.add_label(label_offset);
98 line_builder.add_points(points_offset);
99 line_builder.add_color(color);
James Kuszmaul19217a42022-06-17 10:54:29 -0700100 line_builder.add_style(style_offset);
James Kuszmaul48671362020-12-24 13:54:16 -0800101 lines_.push_back(line_builder.Finish());
102}
103
104void Plotter::MaybeFinishFigure() {
105 if (!lines_.empty()) {
106 const flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Line>>>
107 lines_offset = builder_.fbb()->CreateVector(lines_);
108 auto figure_builder = builder_.MakeBuilder<Figure>();
109 figure_builder.add_title(figure_title_);
110 figure_builder.add_position(position_);
111 figure_builder.add_lines(lines_offset);
112 figure_builder.add_xlabel(xlabel_);
113 figure_builder.add_share_x_axis(share_x_axis_);
114 figure_builder.add_ylabel(ylabel_);
115 figures_.push_back(figure_builder.Finish());
116 }
117 lines_.clear();
118 figure_title_.o = 0;
119 xlabel_.o = 0;
120 ylabel_.o = 0;
121 position_.o = 0;
122 share_x_axis_ = false;
123 color_wheel_position_ = 0;
124}
125
126void Plotter::Publish() {
127 MaybeFinishFigure();
128 const flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Figure>>>
129 figures_offset = builder_.fbb()->CreateVector(figures_);
130
131 auto plot_builder = builder_.MakeBuilder<Plot>();
132 plot_builder.add_title(title_);
133 plot_builder.add_figures(figures_offset);
134
milind1f1dca32021-07-03 13:50:07 -0700135 CHECK_EQ(builder_.Send(plot_builder.Finish()),
136 aos::RawSender::Error::kOk);
James Kuszmaul48671362020-12-24 13:54:16 -0800137
138 builder_ = plot_sender_.MakeBuilder();
139
140 title_.o = 0;
141 figures_.clear();
142 next_top_ = 0;
143}
144
145} // namespace analysis
146} // namespace frc971