Implement interface for using web plotter from C++
It's not actually usable yet due to ODR violations created by
abseil being compiled into libwebrtc_full.a, but it does work based
on testing I've done with using websockets for data transfer.
Change-Id: I574570c7b5c85df9e53321bfb971a608d20b9803
diff --git a/frc971/analysis/in_process_plotter.h b/frc971/analysis/in_process_plotter.h
new file mode 100644
index 0000000..3d7a037
--- /dev/null
+++ b/frc971/analysis/in_process_plotter.h
@@ -0,0 +1,79 @@
+#ifndef FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_
+#define FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_
+
+#include <vector>
+
+#include "aos/events/simulated_event_loop.h"
+#include "aos/network/web_proxy.h"
+#include "frc971/analysis/plot_data_generated.h"
+
+namespace frc971 {
+namespace analysis {
+
+// This class wraps the WebProxy class to provide a convenient C++ interface to
+// dynamically generate plots.
+// Currently, the main useful interface that this provides is a matplotlib-like
+// interface--see in_process_plotter_demo.cc for sample usage. It doesn't
+// precisely follow matplotlib's conventions, but the basic style does mimic
+// matplotlib. Future iterations may ditch this in favor of a more modern
+// interface where we actually return handles for plots and lines and the such.
+//
+// Note that currently the port for the seb server is hard-coded to 8080, so
+// only one instance of the Plotter can be present at once.
+//
+// You must call Spin() for the web server to actually do anything helpful.
+class Plotter {
+ public:
+ Plotter();
+
+ // matplotlib-like interface
+ // The basic pattern is:
+ // 1) Call Figure()
+ // 2) Setup the lines, labels, etc. for the figure.
+ // 3) Repeat 1-2 however many times.
+ // 4) Call Publish().
+ // 5) Repeat 1-5 however many times.
+ //
+ // Publish() actually pushes the figures that you setup to the web-page,
+ // either with an autogenerated title or the title set by Title(). All state
+ // is cleared (or should be cleared) by the call to Publish().
+
+ // Sets the title for the current set of plots; if you
+ void Title(std::string_view title);
+ void AddFigure(std::string_view title = "", double width = 900,
+ double height = 400);
+ void AddLine(const std::vector<double> &x, const std::vector<double> &y,
+ std::string_view label = "");
+ void ShareXAxis(bool share) { share_x_axis_ = share; }
+ void XLabel(std::string_view label);
+ void YLabel(std::string_view label);
+ void Publish();
+
+ void Spin();
+ private:
+ void MaybeFinishFigure();
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
+ aos::SimulatedEventLoopFactory event_loop_factory_;
+ std::unique_ptr<aos::EventLoop> event_loop_;
+ aos::Sender<Plot> plot_sender_;
+ aos::web_proxy::WebProxy web_proxy_;
+
+ aos::Sender<Plot>::Builder builder_;
+ flatbuffers::Offset<flatbuffers::String> title_;
+ flatbuffers::Offset<flatbuffers::String> figure_title_;
+ flatbuffers::Offset<flatbuffers::String> xlabel_;
+ flatbuffers::Offset<flatbuffers::String> ylabel_;
+ bool share_x_axis_ = false;
+ float next_top_ = 0;
+ flatbuffers::Offset<Position> position_;
+ std::vector<flatbuffers::Offset<Figure>> figures_;
+ std::vector<flatbuffers::Offset<Line>> lines_;
+
+ size_t color_wheel_position_ = 0;
+ std::vector<Color> color_wheel_;
+};
+
+} // namespace analysis
+} // namespace frc971
+#endif // FRC971_ANALYSIS_IN_PROCESS_PLOTTER_H_