JaiaBot 2.7.0+40+ge813615b
JaiaBot micro-AUV software
 
Loading...
Searching...
No Matches
liaison_jaiabot.h
Go to the documentation of this file.
1#ifndef LIAISON_JAIABOT_H
2#define LIAISON_JAIABOT_H
3
4#include <Wt/WAbstractItemModel.h>
5#include <Wt/WEvent.h>
6#include <Wt/WPushButton.h>
7#include <Wt/WSlider.h>
8#include <boost/thread/mutex.hpp>
9#include <boost/units/io.hpp>
10#include <chrono>
11
12#include "goby/zeromq/liaison/liaison_container.h"
13#include <goby/middleware/frontseat/groups.h>
14#include <goby/middleware/gpsd/groups.h>
15#include <goby/middleware/protobuf/frontseat_data.pb.h>
16#include <goby/middleware/protobuf/gpsd.pb.h>
17
18#include "jaiabot/groups.h"
21#include "jaiabot/messages/sensor/salinity.pb.h"
22
23#include "config.pb.h"
24#include "jaiabot/messages/feather.pb.h"
25#include "jaiabot/messages/sensor/pressure_temperature.pb.h"
26#include <Wt/Chart/WCartesianChart.h>
27#include <Wt/WAbstractItemModel.h>
28#include <goby/time/system_clock.h>
29
30namespace jaiabot
31{
32class CommsThread;
33
34class LiaisonJaiabot : public goby::zeromq::LiaisonContainerWithComms<LiaisonJaiabot, CommsThread>
35{
36 public:
37 LiaisonJaiabot(const goby::apps::zeromq::protobuf::LiaisonConfig& cfg,
38 Wt::WContainerWidget* parent = 0);
39
41 void post_node_status(const goby::middleware::frontseat::protobuf::NodeStatus& node_status);
42 void post_tpv(const goby::middleware::protobuf::gpsd::TimePositionVelocity& tpv);
47
48 private:
49 void loop();
50 void focus() override { timer_.start(); }
51 void unfocus() override { timer_.stop(); }
52
53 void vehicle_select(Wt::WString msg);
54 void data_select(Wt::WString msg);
55 void check_add_vehicle(int node_id);
56 void add_data_point(const std::string data_type, double data_point);
57 void key_press(Wt::WKeyEvent key);
58 void key_release(Wt::WKeyEvent key);
59 Wt::WDateTime get_date_time(goby::time::MicroTime mp);
60
61 struct YAxisConfig {
62 std::string title;
63 std::pair<double, double> range;
64 };
65
66 void add_data_type(std::pair<std::string, YAxisConfig>& data_type);
67
68 private:
69 Wt::WComboBox* vehicle_combo_;
70 Wt::WComboBox* data_combo_;
71 Wt::WStackedWidget* vehicle_stack_;
72 Wt::WStackedWidget* data_stack_;
73 Wt::WGroupBox* chart_box;
74
75 struct ChartData {
76 std::map<goby::time::MicroTime, double> data_points;
77 std::string chart_type;
78 YAxisConfig y_axis_config;
79 };
80
81 std::vector<ChartData> chart_data_;
82 std::shared_ptr<Wt::WAbstractItemModel> chart_model_;
83 Wt::Chart::WCartesianChart* chart_ = nullptr;
84
85 // Contains all data types that can be displayed on the chart, along with their Y-axis configurations
86 // Y-axis configurations include the title and range for each data type
87 const std::vector<std::pair<std::string, YAxisConfig>> data_types_ = {
88 {"Pressure", {"Pressure (kPa)", {0, 100}}},
89 {"Salinity", {"Salinity (ppt)", {0, 50}}},
90 {"Temperature", {"Temperature (°C)", {10, 20}}},
91 };
92
93 struct VehicleData
94 {
95 VehicleData(Wt::WStackedWidget*, const protobuf::JaiabotConfig&);
96 VehicleData(const VehicleData&) = delete;
97 VehicleData& operator=(const VehicleData&) = delete;
98
99 std::unique_ptr<Wt::WContainerWidget> vehicle_div;
100
101 struct Controls
102 {
103 Controls(Wt::WContainerWidget* vehicle_div, const protobuf::JaiabotConfig& cfg);
104 Controls(const Controls&) = delete;
105 Controls& operator=(const Controls&) = delete;
106
107 Wt::WSlider* timeout_slider{0};
108 Wt::WText* timeout_text{0};
109 Wt::WSlider* dive_slider{0};
110 Wt::WText* dive_text{0};
111 Wt::WSlider* motor_slider{0};
112 Wt::WText* motor_text{0};
113 Wt::WSlider* port_elevator_slider{0};
114 Wt::WSlider* rudder_slider{0};
115
116 Wt::WSlider* stbd_elevator_slider{0};
117 Wt::WText* fins_text{0};
118 Wt::WText* ack_text{0};
119
121
122 // must be static, not sure why (segfault in JSignal otherwise)
123 static void timeout_slider_moved(int value, Wt::WText* text)
124 {
125 std::cout << "slider moved: " << text << std::endl;
126
127 text->setText(timeout_text_from_value(value));
128 }
129
130 static void dive_slider_moved(int value, Wt::WText* text)
131 {
132 text->setText(dive_text_from_value(value));
133 }
134
135 static void dive_button_clicked() { dive_start_ = true; }
136
137 static void motor_slider_moved(int value, Wt::WText* text)
138 {
139 text->setText(motor_text_from_value(value));
140 }
141
142 static void port_elevator_slider_moved(int value, Wt::WText* text,
143 Wt::WSlider* stbd_elevator, Wt::WSlider* rudder)
144 {
145 text->setText(fins_text_from_value(value, stbd_elevator->value(), rudder->value()));
146 }
147
148 static void stbd_elevator_slider_moved(int value, Wt::WText* text,
149 Wt::WSlider* port_elevator, Wt::WSlider* rudder)
150 {
151 text->setText(fins_text_from_value(port_elevator->value(), value, rudder->value()));
152 }
153 static void rudder_slider_moved(int value, Wt::WText* text, Wt::WSlider* port_elevator,
154 Wt::WSlider* stbd_elevator)
155 {
156 text->setText(
157 fins_text_from_value(port_elevator->value(), stbd_elevator->value(), value));
158 }
159
161 {
162 port_elevator_slider->setValue(value);
163 fins_text->setText(fins_text_from_value(port_elevator_slider->value(),
164 stbd_elevator_slider->value(),
165 rudder_slider->value()));
166 }
167
169 {
170 stbd_elevator_slider->setValue(value);
171 fins_text->setText(fins_text_from_value(port_elevator_slider->value(),
172 stbd_elevator_slider->value(),
173 rudder_slider->value()));
174 }
175
176 void set_rudder_value(int value)
177 {
178 rudder_slider->setValue(value);
179 fins_text->setText(fins_text_from_value(port_elevator_slider->value(),
180 stbd_elevator_slider->value(),
181 rudder_slider->value()));
182 }
183
184 void set_motor_value(int value)
185 {
186 motor_slider->setValue(value);
187 motor_text->setText(motor_text_from_value(motor_slider->value()));
188 }
189
190 void set_timeout_value(int value)
191 {
192 timeout_slider->setValue(value);
193 timeout_text->setText(timeout_text_from_value(timeout_slider->value()));
194 }
195
196 void set_dive_value(int value)
197 {
198 dive_slider->setValue(value);
199 dive_text->setText(dive_text_from_value(dive_slider->value()));
200 }
201 };
202
203 Controls low_level_control;
204
205 int index_in_stack{0};
206
207 static std::string timeout_text_from_value(int value)
208 {
209 return "Timeout (X-/V+): " + std::to_string(value);
210 }
211
212 static std::string dive_text_from_value(int value)
213 {
214 return "Dive (Y-/U+): " + std::to_string(value);
215 }
216
217 static std::string motor_text_from_value(int value)
218 {
219 return "Motor (W-/R+): " + std::to_string(value);
220 }
221 static std::string fins_text_from_value(int port_elevator_value, int stbd_elevator_value,
222 int rudder_value)
223 {
224 return "Port Elevator (A-/Q+ or D-/E+ for both): " +
225 std::to_string(port_elevator_value) +
226 "<br/>Starboard Elevator (G-/T+ or D-/E+ for both): " +
227 std::to_string(stbd_elevator_value) +
228 "<br/>Rudder (S-/F+): " + std::to_string(rudder_value);
229 }
230 };
231
232 // vehicle id to Data
233 std::map<int, std::unique_ptr<VehicleData>> vehicle_data_;
234
235 // convenient info shown on vehicle's liaison
236 Wt::WText* bot_node_status_text_;
237 Wt::WText* bot_tpv_text_;
238 Wt::WText* bot_pt_text_;
239 Wt::WText* bot_salinity_text_;
240 Wt::WText* bot_imu_text_;
241 Wt::WText* bot_low_control_text_;
242
243 // currently shown vehicle id
244 int current_vehicle_{-1};
245
246 // currently shown data_type
247 std::string current_data_type_{""};
248
249
250 bool motor_go_{false};
251 static bool dive_start_;
252 static std::chrono::system_clock::time_point dive_expire_;
253
254 Wt::WTimer timer_;
255 friend class CommsThread;
256 const protobuf::JaiabotConfig& cfg_;
257};
258
259class CommsThread : public goby::zeromq::LiaisonCommsThread<LiaisonJaiabot>
260{
261 public:
262 CommsThread(LiaisonJaiabot* tab, const goby::apps::zeromq::protobuf::LiaisonConfig& config,
263 int index)
264 : LiaisonCommsThread<LiaisonJaiabot>(tab, config, index), tab_(tab)
265 {
266 interprocess().subscribe<groups::control_ack>(
267 [this](const protobuf::LowControlAck& ack)
268 { tab_->post_to_wt([=]() { tab_->post_control_ack(ack); }); });
269
270 // post the NodeStatus message in its own box
271 interprocess().subscribe<goby::middleware::frontseat::groups::node_status>(
272 [this](const goby::middleware::frontseat::protobuf::NodeStatus& node_status)
273 { tab_->post_to_wt([=]() { tab_->post_node_status(node_status); }); });
274
275 // post the tpv in its own box
276 interprocess().subscribe<goby::middleware::groups::gpsd::tpv>(
277 [this](const goby::middleware::protobuf::gpsd::TimePositionVelocity& tpv)
278 { tab_->post_to_wt([=]() { tab_->post_tpv(tpv); }); });
279
280 // post the pt data in its own box
281 interprocess().subscribe<groups::pressure_temperature>(
283 { tab_->post_to_wt([=]() { tab_->post_pt(pt); }); });
284
285 // post the salinity data in its own box
286 interprocess().subscribe<groups::salinity>(
287 [this](const jaiabot::protobuf::SalinityData& salinity)
288 { tab_->post_to_wt([=]() { tab_->post_salinity(salinity); }); });
289
290 // post the imu data in its own box
291 interprocess().subscribe<groups::imu>(
292 [this](const jaiabot::protobuf::IMUData& imu)
293 { tab_->post_to_wt([=]() { tab_->post_imu(imu); }); });
294
295 // post the control surfaces data in its own box
296 interprocess().subscribe<groups::low_control>(
297 [this](const jaiabot::protobuf::LowControl& low_control)
298 { tab_->post_to_wt([=]() { tab_->post_low_control(low_control); }); });
299
300 } // namespace jaiabot
302
303 private:
304 friend class LiaisonJaiabot;
305 LiaisonJaiabot* tab_;
306};
307
308} // namespace jaiabot
309
310#endif
CommsThread(LiaisonJaiabot *tab, const goby::apps::zeromq::protobuf::LiaisonConfig &config, int index)
void post_imu(const jaiabot::protobuf::IMUData &imu)
void post_control_ack(const protobuf::LowControlAck &ack)
void post_tpv(const goby::middleware::protobuf::gpsd::TimePositionVelocity &tpv)
void post_low_control(const jaiabot::protobuf::LowControl &low_control)
LiaisonJaiabot(const goby::apps::zeromq::protobuf::LiaisonConfig &cfg, Wt::WContainerWidget *parent=0)
void post_pt(const jaiabot::protobuf::PressureTemperatureData &pt)
void post_node_status(const goby::middleware::frontseat::protobuf::NodeStatus &node_status)
void post_salinity(const jaiabot::protobuf::SalinityData &salinity)
constexpr goby::middleware::Group imu
Definition groups.h:37
constexpr goby::middleware::Group pressure_temperature
Definition groups.h:38
constexpr goby::middleware::Group low_control
Definition groups.h:64
constexpr goby::middleware::Group salinity
Definition groups.h:42
constexpr goby::middleware::Group control_ack
Definition groups.h:65
static void dive_slider_moved(int value, Wt::WText *text)
static void timeout_slider_moved(int value, Wt::WText *text)
static void rudder_slider_moved(int value, Wt::WText *text, Wt::WSlider *port_elevator, Wt::WSlider *stbd_elevator)
Controls & operator=(const Controls &)=delete
Controls(Wt::WContainerWidget *vehicle_div, const protobuf::JaiabotConfig &cfg)
static void stbd_elevator_slider_moved(int value, Wt::WText *text, Wt::WSlider *port_elevator, Wt::WSlider *rudder)
static void port_elevator_slider_moved(int value, Wt::WText *text, Wt::WSlider *stbd_elevator, Wt::WSlider *rudder)
static void motor_slider_moved(int value, Wt::WText *text)