James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 1 | #ifndef FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_ |
| 2 | #define FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_ |
| 3 | |
| 4 | #include <vector> |
| 5 | |
| 6 | #include "aos/events/simulated_event_loop.h" |
| 7 | #include "aos/network/web_proxy.h" |
| 8 | #include "frc971/analysis/plot_data_generated.h" |
| 9 | |
| 10 | namespace frc971 { |
| 11 | namespace analysis { |
| 12 | |
| 13 | // This class wraps the WebProxy class to provide a convenient C++ interface to |
| 14 | // dynamically generate plots. |
| 15 | // Currently, the main useful interface that this provides is a matplotlib-like |
| 16 | // interface--see in_process_plotter_demo.cc for sample usage. It doesn't |
| 17 | // precisely follow matplotlib's conventions, but the basic style does mimic |
| 18 | // matplotlib. Future iterations may ditch this in favor of a more modern |
| 19 | // interface where we actually return handles for plots and lines and the such. |
| 20 | // |
| 21 | // Note that currently the port for the seb server is hard-coded to 8080, so |
| 22 | // only one instance of the Plotter can be present at once. |
| 23 | // |
| 24 | // You must call Spin() for the web server to actually do anything helpful. |
| 25 | class Plotter { |
| 26 | public: |
| 27 | Plotter(); |
| 28 | |
| 29 | // matplotlib-like interface |
| 30 | // The basic pattern is: |
| 31 | // 1) Call Figure() |
Philipp Schrader | a671252 | 2023-07-05 20:25:11 -0700 | [diff] [blame^] | 32 | // 2) Set up the lines, labels, etc. for the figure. |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 33 | // 3) Repeat 1-2 however many times. |
| 34 | // 4) Call Publish(). |
| 35 | // 5) Repeat 1-5 however many times. |
| 36 | // |
| 37 | // Publish() actually pushes the figures that you setup to the web-page, |
| 38 | // either with an autogenerated title or the title set by Title(). All state |
| 39 | // is cleared (or should be cleared) by the call to Publish(). |
| 40 | |
| 41 | // Sets the title for the current set of plots; if you |
| 42 | void Title(std::string_view title); |
Austin Schuh | 5ec17ef | 2022-07-15 14:37:16 -0700 | [diff] [blame] | 43 | void AddFigure(std::string_view title = "", double width = 0, |
| 44 | double height = 0); |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 45 | struct LineOptions { |
| 46 | std::string_view label = ""; |
| 47 | std::string_view line_style = "*-"; |
| 48 | std::string_view color = ""; |
Austin Schuh | 69d0b73 | 2022-07-20 21:19:32 -0700 | [diff] [blame] | 49 | double point_size = 3.0; |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 50 | }; |
| 51 | |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 52 | void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 53 | std::string_view label) { |
| 54 | AddLine(x, y, LineOptions{.label = label}); |
| 55 | } |
| 56 | void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
| 57 | std::string_view label, std::string_view line_style) { |
| 58 | AddLine(x, y, LineOptions{.label = label, .line_style = line_style}); |
| 59 | } |
| 60 | void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
| 61 | LineOptions options); |
| 62 | |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 63 | void ShareXAxis(bool share) { share_x_axis_ = share; } |
| 64 | void XLabel(std::string_view label); |
| 65 | void YLabel(std::string_view label); |
| 66 | void Publish(); |
| 67 | |
| 68 | void Spin(); |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 69 | |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 70 | private: |
| 71 | void MaybeFinishFigure(); |
| 72 | |
| 73 | aos::FlatbufferDetachedBuffer<aos::Configuration> config_; |
| 74 | aos::SimulatedEventLoopFactory event_loop_factory_; |
| 75 | std::unique_ptr<aos::EventLoop> event_loop_; |
| 76 | aos::Sender<Plot> plot_sender_; |
| 77 | aos::web_proxy::WebProxy web_proxy_; |
| 78 | |
| 79 | aos::Sender<Plot>::Builder builder_; |
| 80 | flatbuffers::Offset<flatbuffers::String> title_; |
| 81 | flatbuffers::Offset<flatbuffers::String> figure_title_; |
| 82 | flatbuffers::Offset<flatbuffers::String> xlabel_; |
| 83 | flatbuffers::Offset<flatbuffers::String> ylabel_; |
| 84 | bool share_x_axis_ = false; |
| 85 | float next_top_ = 0; |
| 86 | flatbuffers::Offset<Position> position_; |
| 87 | std::vector<flatbuffers::Offset<Figure>> figures_; |
| 88 | std::vector<flatbuffers::Offset<Line>> lines_; |
| 89 | |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 90 | struct ColorWheelColor { |
| 91 | std::string name; |
| 92 | Color color; |
| 93 | }; |
| 94 | |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 95 | size_t color_wheel_position_ = 0; |
Austin Schuh | ea62f60 | 2022-07-18 16:53:04 -0700 | [diff] [blame] | 96 | std::vector<ColorWheelColor> color_wheel_; |
James Kuszmaul | 4867136 | 2020-12-24 13:54:16 -0800 | [diff] [blame] | 97 | }; |
| 98 | |
| 99 | } // namespace analysis |
| 100 | } // namespace frc971 |
| 101 | #endif // FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_ |