marti_nav_plan_plugin.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2021, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
31 
32 // C++ standard libraries
33 #include <cstdio>
34 #include <vector>
35 
36 // QT libraries
37 #include <QDialog>
38 #include <QGLWidget>
39 #include <QPainter>
40 #include <QPalette>
41 
42 #include <opencv2/core/core.hpp>
43 
44 // ROS libraries
45 #include <ros/master.h>
46 
49 #include <swri_route_util/util.h>
52 
53 #include <marti_nav_msgs/Plan.h>
54 
55 // Declare plugin
57 
59 
60 namespace sru = swri_route_util;
61 namespace stu = swri_transform_util;
62 
63 namespace mapviz_plugins
64 {
65  MartiNavPlanPlugin::MartiNavPlanPlugin() : config_widget_(new QWidget()), draw_style_(STYLE_LINES)
66  {
67  ui_.setupUi(config_widget_);
68 
69  ui_.color->setColor(Qt::green);
70  // Set background white
71  QPalette p(config_widget_->palette());
72  p.setColor(QPalette::Background, Qt::white);
73  config_widget_->setPalette(p);
74  // Set status text red
75  QPalette p3(ui_.status->palette());
76  p3.setColor(QPalette::Text, Qt::red);
77  ui_.status->setPalette(p3);
78  QObject::connect(ui_.selecttopic, SIGNAL(clicked()), this,
79  SLOT(SelectTopic()));
80  QObject::connect(ui_.topic, SIGNAL(editingFinished()), this,
81  SLOT(TopicEdited()));
82  QObject::connect(ui_.selectpositiontopic, SIGNAL(clicked()), this,
83  SLOT(SelectPositionTopic()));
84  QObject::connect(ui_.positiontopic, SIGNAL(editingFinished()), this,
85  SLOT(PositionTopicEdited()));
86  QObject::connect(ui_.drawstyle, SIGNAL(activated(QString)), this,
87  SLOT(SetDrawStyle(QString)));
88  QObject::connect(ui_.color, SIGNAL(colorEdited(const QColor&)), this,
89  SLOT(DrawIcon()));
90  }
91 
93  {
94  }
95 
97  {
98  if (icon_)
99  {
100  QPixmap icon(16, 16);
101  icon.fill(Qt::transparent);
102 
103  QPainter painter(&icon);
104  painter.setRenderHint(QPainter::Antialiasing, true);
105 
106  QPen pen(ui_.color->color());
107 
109  {
110  pen.setWidth(7);
111  pen.setCapStyle(Qt::RoundCap);
112  painter.setPen(pen);
113  painter.drawPoint(8, 8);
114  }
115  else if (draw_style_ & STYLE_LINES)
116  {
117  pen.setWidth(3);
118  pen.setCapStyle(Qt::FlatCap);
119  painter.setPen(pen);
120  painter.drawLine(1, 14, 14, 1);
121  }
122 
123  icon_->SetPixmap(icon);
124  }
125  }
126 
128  {
129  if (style == "lines")
130  {
132  }
133  else if (style == "points")
134  {
136  }
137  else if (style == "points and lines")
138  {
140  }
141  DrawIcon();
142  }
143 
145  {
146  ros::master::TopicInfo topic =
147  mapviz::SelectTopicDialog::selectTopic("marti_nav_msgs/Plan");
148 
149  if (topic.name.empty())
150  {
151  return;
152  }
153 
154  ui_.topic->setText(QString::fromStdString(topic.name));
155  TopicEdited();
156  }
157 
159  {
160  ros::master::TopicInfo topic =
161  mapviz::SelectTopicDialog::selectTopic("marti_nav_msgs/PlanTrack");
162 
163  if (topic.name.empty())
164  {
165  return;
166  }
167 
168  ui_.positiontopic->setText(QString::fromStdString(topic.name));
170  }
171 
173  {
174  std::string topic = ui_.topic->text().trimmed().toStdString();
175  if (topic != topic_)
176  {
177  src_route_.reset();
178 
180 
181  topic_ = topic;
182  if (!topic.empty())
183  {
184  route_sub_ =
186 
187  ROS_INFO("Subscribing to %s", topic_.c_str());
188  }
189  }
190  }
191 
193  {
194  std::string topic = ui_.positiontopic->text().trimmed().toStdString();
195  if (topic != position_topic_)
196  {
197  src_route_position_.reset();
199 
200  if (!topic.empty())
201  {
202  position_topic_ = topic;
205 
206  ROS_INFO("Subscribing to %s", position_topic_.c_str());
207  }
208  }
209  }
210 
212  const marti_nav_msgs::PlanTrackConstPtr& msg)
213  {
214  src_route_position_ = msg;
215  }
216 
217  void MartiNavPlanPlugin::RouteCallback(const marti_nav_msgs::PlanConstPtr& msg)
218  {
219  src_route_ = msg;
220  }
221 
222  void MartiNavPlanPlugin::PrintError(const std::string& message)
223  {
224  PrintErrorHelper(ui_.status, message, 1.0);
225  }
226 
227  void MartiNavPlanPlugin::PrintInfo(const std::string& message)
228  {
229  PrintInfoHelper(ui_.status, message, 1.0);
230  }
231 
232  void MartiNavPlanPlugin::PrintWarning(const std::string& message)
233  {
234  PrintWarningHelper(ui_.status, message, 1.0);
235  }
236 
237  QWidget* MartiNavPlanPlugin::GetConfigWidget(QWidget* parent)
238  {
239  config_widget_->setParent(parent);
240 
241  return config_widget_;
242  }
243 
244  bool MartiNavPlanPlugin::Initialize(QGLWidget* canvas)
245  {
246  canvas_ = canvas;
247 
248  DrawIcon();
249 
250  initialized_ = true;
251  return true;
252  }
253 
254  void MartiNavPlanPlugin::Draw(double x, double y, double scale)
255  {
256  if (!src_route_ || src_route_->points.size() == 0)
257  {
258  PrintError("No valid route received.");
259  return;
260  }
261 
262  marti_nav_msgs::Plan route = *src_route_;
263  if (route.header.frame_id.empty())
264  {
265  route.header.frame_id = "/wgs84";
266  }
267 
269  if (!GetTransform(route.header.frame_id, ros::Time(), transform))
270  {
271  PrintError("Failed to transform route");
272  return;
273  }
274 
275  sru::transform(route, transform, target_frame_);
276  sru::projectToXY(route);
277  sru::fillOrientations(route);
278 
279  DrawRoute(route);
280 
281  bool ok = true;
283  {
284  marti_nav_msgs::PlanPoint point;
285  sru::interpolatePlanPosition(route, src_route_position_->plan_position, point, true);
286  if (src_route_position_->plan_id == route.id)
287  {
288  DrawRoutePoint(point);
289  }
290  else
291  {
292  PrintError("Failed to find plan position in plan.");
293  ok = false;
294  }
295  }
296 
297  if (ok)
298  {
299  PrintInfo("OK");
300  }
301  }
302 
303  void MartiNavPlanPlugin::DrawStopWaypoint(double x, double y)
304  {
305  const double a = 2;
306  const double S = a * 2.414213562373095;
307 
308  glBegin(GL_POLYGON);
309 
310  glColor3f(1.0, 0.0, 0.0);
311 
312  glVertex2d(x + S / 2.0, y - a / 2.0);
313  glVertex2d(x + S / 2.0, y + a / 2.0);
314  glVertex2d(x + a / 2.0, y + S / 2.0);
315  glVertex2d(x - a / 2.0, y + S / 2.0);
316  glVertex2d(x - S / 2.0, y + a / 2.0);
317  glVertex2d(x - S / 2.0, y - a / 2.0);
318  glVertex2d(x - a / 2.0, y - S / 2.0);
319  glVertex2d(x + a / 2.0, y - S / 2.0);
320 
321  glEnd();
322  }
323 
324  void MartiNavPlanPlugin::DrawRoute(const marti_nav_msgs::Plan& route)
325  {
326  const QColor color = ui_.color->color();
327  glColor4d(color.redF(), color.greenF(), color.blueF(), 1.0);
328 
329  if (draw_style_ & STYLE_LINES)
330  {
331  glLineWidth(3);
332  glBegin(GL_LINE_STRIP);
333  for (size_t i = 0; i < route.points.size(); i++)
334  {
335  glVertex2d(route.points[i].x,
336  route.points[i].y);
337  }
338  glEnd();
339  }
340 
342  {
343  glPointSize(5);
344  glBegin(GL_POINTS);
345  for (size_t i = 0; i < route.points.size(); i++)
346  {
347  glVertex2d(route.points[i].x,
348  route.points[i].y);
349  }
350  glEnd();
351  }
352  }
353 
354  void MartiNavPlanPlugin::DrawRoutePoint(const marti_nav_msgs::PlanPoint& point)
355  {
356  const double arrow_size = ui_.iconsize->value();
357 
358  tf::Vector3 v1(arrow_size, 0.0, 0.0);
359  tf::Vector3 v2(0.0, arrow_size / 2.0, 0.0);
360  tf::Vector3 v3(0.0, -arrow_size / 2.0, 0.0);
361 
363  tf::Vector3 p(point.x, point.y, point.z);
364  tf::Transform point_g(q, p);
365 
366  v1 = point_g * v1;
367  v2 = point_g * v2;
368  v3 = point_g * v3;
369 
370  const QColor color = ui_.positioncolor->color();
371  glLineWidth(3);
372  glBegin(GL_POLYGON);
373  glColor4d(color.redF(), color.greenF(), color.blueF(), 1.0);
374  glVertex2d(v1.x(), v1.y());
375  glVertex2d(v2.x(), v2.y());
376  glVertex2d(v3.x(), v3.y());
377  glEnd();
378  }
379 
380  void MartiNavPlanPlugin::LoadConfig(const YAML::Node& node, const std::string& path)
381  {
382  if (node["topic"])
383  {
384  std::string route_topic;
385  node["topic"] >> route_topic;
386  ui_.topic->setText(route_topic.c_str());
387  }
388  if (node["color"])
389  {
390  std::string color;
391  node["color"] >> color;
392  ui_.color->setColor(QColor(color.c_str()));
393  }
394  if (node["postopic"])
395  {
396  std::string pos_topic;
397  node["postopic"] >> pos_topic;
398  ui_.positiontopic->setText(pos_topic.c_str());
399  }
400  if (node["poscolor"])
401  {
402  std::string poscolor;
403  node["poscolor"] >> poscolor;
404  ui_.positioncolor->setColor(QColor(poscolor.c_str()));
405  }
406 
407  if (node["draw_style"])
408  {
409  std::string draw_style;
410  node["draw_style"] >> draw_style;
411 
412  if (draw_style == "lines")
413  {
415  ui_.drawstyle->setCurrentIndex(0);
416  }
417  else if (draw_style == "points")
418  {
420  ui_.drawstyle->setCurrentIndex(1);
421  }
422  else if (draw_style == "points and lines")
423  {
425  ui_.drawstyle->setCurrentIndex(2);
426  }
427  }
428 
429  TopicEdited();
431  }
432 
433  void MartiNavPlanPlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
434  {
435  std::string route_topic = ui_.topic->text().toStdString();
436  emitter << YAML::Key << "topic" << YAML::Value << route_topic;
437 
438  std::string color = ui_.color->color().name().toStdString();
439  emitter << YAML::Key << "color" << YAML::Value << color;
440 
441  std::string pos_topic = ui_.positiontopic->text().toStdString();
442  emitter << YAML::Key << "postopic" << YAML::Value << pos_topic;
443 
444  std::string pos_color = ui_.positioncolor->color().name().toStdString();
445  emitter << YAML::Key << "poscolor" << YAML::Value << pos_color;
446 
447  std::string draw_style = ui_.drawstyle->currentText().toStdString();
448  emitter << YAML::Key << "draw_style" << YAML::Value << draw_style;
449  }
450 }
QWidget * GetConfigWidget(QWidget *parent)
bool GetTransform(const ros::Time &stamp, swri_transform_util::Transform &transform, bool use_latest_transforms=true)
static ros::master::TopicInfo selectTopic(const std::string &datatype, QWidget *parent=0)
void RouteCallback(const marti_nav_msgs::PlanConstPtr &msg)
IconWidget * icon_
ros::NodeHandle node_
void DrawRoutePoint(const marti_nav_msgs::PlanPoint &point)
marti_nav_msgs::PlanConstPtr src_route_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
static void PrintWarningHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
static void PrintErrorHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
void SaveConfig(YAML::Emitter &emitter, const std::string &path)
std::string target_frame_
void Draw(double x, double y, double scale)
void LoadConfig(const YAML::Node &node, const std::string &path)
static void PrintInfoHelper(QLabel *status_label, const std::string &message, double throttle=0.0)
void SetPixmap(QPixmap pixmap)
static Quaternion createQuaternionFromYaw(double yaw)
void PrintWarning(const std::string &message)
void PrintError(const std::string &message)
#define ROS_INFO(...)
void PositionCallback(const marti_nav_msgs::PlanTrackConstPtr &msg)
ROSCPP_DECL bool ok()
void DrawRoute(const marti_nav_msgs::Plan &route)
void transform(marti_nav_msgs::Path &path, const swri_transform_util::Transform &transform, const std::string &target_frame)
marti_nav_msgs::PlanTrackConstPtr src_route_position_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void PrintInfo(const std::string &message)


mapviz_plugins
Author(s): Marc Alban
autogenerated on Fri Dec 16 2022 03:59:33