James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame^] | 1 | #include "frc971/analysis/in_process_plotter.h" |
| 2 | |
| 3 | #include "aos/configuration.h" |
| 4 | |
| 5 | namespace frc971 { |
| 6 | namespace analysis { |
| 7 | |
| 8 | namespace { |
| 9 | const char *kDataPath = "frc971/analysis"; |
| 10 | const char *kConfigPath = "frc971/analysis/plotter.json"; |
| 11 | } // namespace |
| 12 | |
| 13 | Plotter::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")), |
| 18 | web_proxy_(event_loop_.get(), -1), |
| 19 | 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)); |
| 28 | } |
| 29 | |
| 30 | void Plotter::Spin() { event_loop_factory_.Run(); } |
| 31 | |
| 32 | void Plotter::Title(std::string_view title) { |
| 33 | title_ = builder_.fbb()->CreateString(title); |
| 34 | } |
| 35 | |
| 36 | void Plotter::AddFigure(std::string_view title, double width, double height) { |
| 37 | MaybeFinishFigure(); |
| 38 | |
| 39 | if (!title.empty()) { |
| 40 | figure_title_ = builder_.fbb()->CreateString(title); |
| 41 | } |
| 42 | |
| 43 | // For positioning, just stack figures vertically. |
| 44 | auto position_builder = builder_.MakeBuilder<Position>(); |
| 45 | position_builder.add_top(next_top_); |
| 46 | position_builder.add_left(0); |
| 47 | position_builder.add_width(width); |
| 48 | position_builder.add_height(height); |
| 49 | position_ = position_builder.Finish(); |
| 50 | |
| 51 | next_top_ += height; |
| 52 | } |
| 53 | |
| 54 | void Plotter::XLabel(std::string_view label) { |
| 55 | xlabel_ = builder_.fbb()->CreateString(label); |
| 56 | } |
| 57 | |
| 58 | void Plotter::YLabel(std::string_view label) { |
| 59 | ylabel_ = builder_.fbb()->CreateString(label); |
| 60 | } |
| 61 | |
| 62 | void Plotter::AddLine(const std::vector<double> &x, |
| 63 | const std::vector<double> &y, std::string_view label) { |
| 64 | CHECK_EQ(x.size(), y.size()); |
| 65 | CHECK(!position_.IsNull()) |
| 66 | << "You must call AddFigure() before calling AddLine()."; |
| 67 | |
| 68 | flatbuffers::Offset<flatbuffers::String> label_offset; |
| 69 | if (!label.empty()) { |
| 70 | label_offset = builder_.fbb()->CreateString(label); |
| 71 | } |
| 72 | |
| 73 | std::vector<Point> points; |
| 74 | for (size_t ii = 0; ii < x.size(); ++ii) { |
| 75 | points.emplace_back(x[ii], y[ii]); |
| 76 | } |
| 77 | const flatbuffers::Offset<flatbuffers::Vector<const Point*>> |
| 78 | points_offset = builder_.fbb()->CreateVectorOfStructs(points); |
| 79 | |
| 80 | const Color *color = &color_wheel_.at(color_wheel_position_); |
| 81 | color_wheel_position_ = (color_wheel_position_ + 1) % color_wheel_.size(); |
| 82 | |
| 83 | auto line_builder = builder_.MakeBuilder<Line>(); |
| 84 | line_builder.add_label(label_offset); |
| 85 | line_builder.add_points(points_offset); |
| 86 | line_builder.add_color(color); |
| 87 | lines_.push_back(line_builder.Finish()); |
| 88 | } |
| 89 | |
| 90 | void Plotter::MaybeFinishFigure() { |
| 91 | if (!lines_.empty()) { |
| 92 | const flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Line>>> |
| 93 | lines_offset = builder_.fbb()->CreateVector(lines_); |
| 94 | auto figure_builder = builder_.MakeBuilder<Figure>(); |
| 95 | figure_builder.add_title(figure_title_); |
| 96 | figure_builder.add_position(position_); |
| 97 | figure_builder.add_lines(lines_offset); |
| 98 | figure_builder.add_xlabel(xlabel_); |
| 99 | figure_builder.add_share_x_axis(share_x_axis_); |
| 100 | figure_builder.add_ylabel(ylabel_); |
| 101 | figures_.push_back(figure_builder.Finish()); |
| 102 | } |
| 103 | lines_.clear(); |
| 104 | figure_title_.o = 0; |
| 105 | xlabel_.o = 0; |
| 106 | ylabel_.o = 0; |
| 107 | position_.o = 0; |
| 108 | share_x_axis_ = false; |
| 109 | color_wheel_position_ = 0; |
| 110 | } |
| 111 | |
| 112 | void Plotter::Publish() { |
| 113 | MaybeFinishFigure(); |
| 114 | const flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Figure>>> |
| 115 | figures_offset = builder_.fbb()->CreateVector(figures_); |
| 116 | |
| 117 | auto plot_builder = builder_.MakeBuilder<Plot>(); |
| 118 | plot_builder.add_title(title_); |
| 119 | plot_builder.add_figures(figures_offset); |
| 120 | |
| 121 | builder_.Send(plot_builder.Finish()); |
| 122 | |
| 123 | builder_ = plot_sender_.MakeBuilder(); |
| 124 | |
| 125 | title_.o = 0; |
| 126 | figures_.clear(); |
| 127 | next_top_ = 0; |
| 128 | } |
| 129 | |
| 130 | } // namespace analysis |
| 131 | } // namespace frc971 |