00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <mapviz_plugins/string_plugin.h>
00032
00033 #include <pluginlib/class_list_macros.h>
00034 #include <mapviz/select_topic_dialog.h>
00035
00036 #include <QFontDialog>
00037
00038 PLUGINLIB_DECLARE_CLASS(
00039 mapviz_plugins,
00040 string,
00041 mapviz_plugins::StringPlugin,
00042 mapviz::MapvizPlugin)
00043
00044 namespace mapviz_plugins
00045 {
00046 const char* StringPlugin::COLOR_KEY = "color";
00047 const char* StringPlugin::FONT_KEY = "font";
00048 const char* StringPlugin::TOPIC_KEY = "topic";
00049 const char* StringPlugin::ANCHOR_KEY = "anchor";
00050 const char* StringPlugin::UNITS_KEY = "units";
00051 const char* StringPlugin::OFFSET_X_KEY = "offset_x";
00052 const char* StringPlugin::OFFSET_Y_KEY = "offset_y";
00053
00054 StringPlugin::StringPlugin() :
00055 config_widget_(new QWidget()),
00056 anchor_(TOP_LEFT),
00057 units_(PIXELS),
00058 offset_x_(0),
00059 offset_y_(0),
00060 has_message_(false),
00061 has_painted_(false),
00062 color_(Qt::black)
00063 {
00064 ui_.setupUi(config_widget_);
00065
00066 QPalette p(config_widget_->palette());
00067 p.setColor(QPalette::Background, Qt::white);
00068 config_widget_->setPalette(p);
00069
00070
00071 QPalette p3(ui_.status->palette());
00072 p3.setColor(QPalette::Text, Qt::red);
00073 ui_.status->setPalette(p3);
00074
00075 QObject::connect(ui_.selecttopic, SIGNAL(clicked()), this, SLOT(SelectTopic()));
00076 QObject::connect(ui_.topic, SIGNAL(editingFinished()), this, SLOT(TopicEdited()));
00077 QObject::connect(ui_.anchor, SIGNAL(activated(QString)), this, SLOT(SetAnchor(QString)));
00078 QObject::connect(ui_.units, SIGNAL(activated(QString)), this, SLOT(SetUnits(QString)));
00079 QObject::connect(ui_.offsetx, SIGNAL(valueChanged(int)), this, SLOT(SetOffsetX(int)));
00080 QObject::connect(ui_.offsety, SIGNAL(valueChanged(int)), this, SLOT(SetOffsetY(int)));
00081 QObject::connect(ui_.font_button, SIGNAL(clicked()), this, SLOT(SelectFont()));
00082 QObject::connect(ui_.color, SIGNAL(colorEdited(const QColor &)), this, SLOT(SelectColor()));
00083
00084 font_.setFamily(tr("Helvetica"));
00085 ui_.font_button->setFont(font_);
00086 ui_.font_button->setText(font_.family());
00087
00088 ui_.color->setColor(color_);
00089 }
00090
00091 StringPlugin::~StringPlugin()
00092 {
00093 }
00094
00095 bool StringPlugin::Initialize(QGLWidget* canvas)
00096 {
00097 canvas_ = canvas;
00098 return true;
00099 }
00100
00101 void StringPlugin::Draw(double x, double y, double scale)
00102 {
00103
00104 }
00105
00106 void StringPlugin::Paint(QPainter* painter, double x, double y, double scale)
00107 {
00108 if (has_message_)
00109 {
00110 painter->save();
00111 painter->resetTransform();
00112 painter->setFont(font_);
00113
00114 if (!has_painted_)
00115 {
00116
00117
00118
00119
00120
00121
00122
00123 QPen invisPen(QBrush(Qt::transparent), 1);
00124 painter->setPen(invisPen);
00125 PaintText(painter);
00126 has_painted_ = true;
00127 }
00128 QPen pen(QBrush(color_), 1);
00129 painter->setPen(pen);
00130 PaintText(painter);
00131
00132 painter->restore();
00133 PrintInfo("OK");
00134 }
00135 else
00136 {
00137 PrintWarning("No messages received.");
00138 }
00139 }
00140
00141 void StringPlugin::PaintText(QPainter* painter)
00142 {
00143
00144 int x_offset = offset_x_;
00145 int y_offset = offset_y_;
00146 if (units_ == PERCENT)
00147 {
00148 x_offset = static_cast<int>((float)(offset_x_ * canvas_->width()) / 100.0);
00149 y_offset = static_cast<int>((float)(offset_y_ * canvas_->height()) / 100.0);
00150 }
00151
00152 int right = static_cast<int>((float)canvas_->width() - message_.size().width()) - x_offset;
00153 int bottom = static_cast<int>((float)canvas_->height() - message_.size().height()) - y_offset;
00154 int yCenter = static_cast<int>((float)canvas_->height() / 2.0 - message_.size().height()/2.0);
00155 int xCenter = static_cast<int>((float)canvas_->width() / 2.0 - message_.size().width()/2.0);
00156
00157 QPoint ulPoint;
00158
00159 switch (anchor_)
00160 {
00161 case TOP_LEFT:
00162 ulPoint.setX(x_offset);
00163 ulPoint.setY(y_offset);
00164 break;
00165 case TOP_CENTER:
00166 ulPoint.setX(xCenter);
00167 ulPoint.setY(y_offset);
00168 break;
00169 case TOP_RIGHT:
00170 ulPoint.setX(right);
00171 ulPoint.setY(y_offset);
00172 break;
00173 case CENTER_LEFT:
00174 ulPoint.setX(x_offset);
00175 ulPoint.setY(yCenter);
00176 break;
00177 case CENTER:
00178 ulPoint.setX(xCenter);
00179 ulPoint.setY(yCenter);
00180 break;
00181 case CENTER_RIGHT:
00182 ulPoint.setX(right);
00183 ulPoint.setY(yCenter);
00184 break;
00185 case BOTTOM_LEFT:
00186 ulPoint.setX(x_offset);
00187 ulPoint.setY(bottom);
00188 break;
00189 case BOTTOM_CENTER:
00190 ulPoint.setX(xCenter);
00191 ulPoint.setY(bottom);
00192 break;
00193 case BOTTOM_RIGHT:
00194 ulPoint.setX(right);
00195 ulPoint.setY(bottom);
00196 break;
00197 }
00198 painter->drawStaticText(ulPoint, message_);
00199 }
00200
00201 void StringPlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00202 {
00203 if (node[TOPIC_KEY])
00204 {
00205 ui_.topic->setText(QString(node[TOPIC_KEY].as<std::string>().c_str()));
00206 TopicEdited();
00207 }
00208
00209 if (node[FONT_KEY])
00210 {
00211 font_.fromString(QString(node[FONT_KEY].as<std::string>().c_str()));
00212 ui_.font_button->setFont(font_);
00213 ui_.font_button->setText(font_.family());
00214 }
00215
00216 if (node[COLOR_KEY])
00217 {
00218 color_ = QColor(node[COLOR_KEY].as<std::string>().c_str());
00219 ui_.color->setColor(QColor(color_.name().toStdString().c_str()));
00220 }
00221
00222 if (node[ANCHOR_KEY])
00223 {
00224 std::string anchor = node[ANCHOR_KEY].as<std::string>();
00225 ui_.anchor->setCurrentIndex(ui_.anchor->findText(anchor.c_str()));
00226 SetAnchor(anchor.c_str());
00227 }
00228
00229 if (node[UNITS_KEY])
00230 {
00231 std::string units = node[UNITS_KEY].as<std::string>();
00232 ui_.units->setCurrentIndex(ui_.units->findText(units.c_str()));
00233 SetUnits(units.c_str());
00234 }
00235
00236 if (node[OFFSET_X_KEY])
00237 {
00238 offset_x_ = node[OFFSET_X_KEY].as<int>();
00239 ui_.offsetx->setValue(offset_x_);
00240 }
00241
00242 if (node[OFFSET_Y_KEY])
00243 {
00244 offset_y_ = node[OFFSET_Y_KEY].as<int>();
00245 ui_.offsety->setValue(offset_y_);
00246 }
00247 }
00248
00249 void StringPlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00250 {
00251 emitter << YAML::Key << FONT_KEY << YAML::Value << font_.toString().toStdString();
00252 emitter << YAML::Key << COLOR_KEY << YAML::Value << color_.name().toStdString();
00253 emitter << YAML::Key << TOPIC_KEY << YAML::Value << ui_.topic->text().toStdString();
00254 emitter << YAML::Key << ANCHOR_KEY << YAML::Value << AnchorToString(anchor_);
00255 emitter << YAML::Key << UNITS_KEY << YAML::Value << UnitsToString(units_);
00256 emitter << YAML::Key << OFFSET_X_KEY << YAML::Value << offset_x_;
00257 emitter << YAML::Key << OFFSET_Y_KEY << YAML::Value << offset_y_;
00258 }
00259
00260 QWidget* StringPlugin::GetConfigWidget(QWidget* parent)
00261 {
00262 config_widget_->setParent(parent);
00263 return config_widget_;
00264 }
00265
00266 void StringPlugin::PrintError(const std::string& message)
00267 {
00268 if (message == ui_.status->text().toStdString())
00269 {
00270 return;
00271 }
00272
00273 ROS_ERROR("Error: %s", message.c_str());
00274 QPalette p(ui_.status->palette());
00275 p.setColor(QPalette::Text, Qt::red);
00276 ui_.status->setPalette(p);
00277 ui_.status->setText(message.c_str());
00278 }
00279
00280 void StringPlugin::PrintInfo(const std::string& message)
00281 {
00282 if (message == ui_.status->text().toStdString())
00283 {
00284 return;
00285 }
00286
00287 ROS_INFO("%s", message.c_str());
00288 QPalette p(ui_.status->palette());
00289 p.setColor(QPalette::Text, Qt::green);
00290 ui_.status->setPalette(p);
00291 ui_.status->setText(message.c_str());
00292 }
00293
00294 void StringPlugin::PrintWarning(const std::string& message)
00295 {
00296 if (message == ui_.status->text().toStdString())
00297 {
00298 return;
00299 }
00300
00301 ROS_WARN("%s", message.c_str());
00302 QPalette p(ui_.status->palette());
00303 p.setColor(QPalette::Text, Qt::darkYellow);
00304 ui_.status->setPalette(p);
00305 ui_.status->setText(message.c_str());
00306 }
00307
00308 void StringPlugin::SelectColor()
00309 {
00310 color_ = ui_.color->color();
00311 }
00312
00313 void StringPlugin::SelectFont()
00314 {
00315 bool ok;
00316 QFont font = QFontDialog::getFont(&ok, font_, canvas_);
00317 if (ok)
00318 {
00319 font_ = font;
00320 message_.prepare(QTransform(), font_);
00321 ui_.font_button->setFont(font_);
00322 ui_.font_button->setText(font_.family());
00323 }
00324 }
00325
00326 void StringPlugin::SelectTopic()
00327 {
00328 ros::master::TopicInfo topic = mapviz::SelectTopicDialog::selectTopic(
00329 "std_msgs/String");
00330
00331 if (!topic.name.empty())
00332 {
00333 ui_.topic->setText(QString::fromStdString(topic.name));
00334 TopicEdited();
00335 }
00336 }
00337
00338 void StringPlugin::TopicEdited()
00339 {
00340 std::string topic = ui_.topic->text().trimmed().toStdString();
00341 if (topic != topic_)
00342 {
00343 initialized_ = false;
00344 has_message_ = false;
00345 PrintWarning("No messages received.");
00346
00347 string_sub_.shutdown();
00348
00349 topic_ = topic;
00350 if (!topic.empty())
00351 {
00352 string_sub_ = node_.subscribe(topic_, 1, &StringPlugin::stringCallback, this);
00353
00354 ROS_INFO("Subscribing to %s", topic_.c_str());
00355 }
00356 }
00357 }
00358
00359 void StringPlugin::SetAnchor(QString anchor)
00360 {
00361 if (anchor == "top left")
00362 {
00363 anchor_ = TOP_LEFT;
00364 }
00365 else if (anchor == "top center")
00366 {
00367 anchor_ = TOP_CENTER;
00368 }
00369 else if (anchor == "top right")
00370 {
00371 anchor_ = TOP_RIGHT;
00372 }
00373 else if (anchor == "center left")
00374 {
00375 anchor_ = CENTER_LEFT;
00376 }
00377 else if (anchor == "center")
00378 {
00379 anchor_ = CENTER;
00380 }
00381 else if (anchor == "center right")
00382 {
00383 anchor_ = CENTER_RIGHT;
00384 }
00385 else if (anchor == "bottom left")
00386 {
00387 anchor_ = BOTTOM_LEFT;
00388 }
00389 else if (anchor == "bottom center")
00390 {
00391 anchor_ = BOTTOM_CENTER;
00392 }
00393 else if (anchor == "bottom right")
00394 {
00395 anchor_ = BOTTOM_RIGHT;
00396 }
00397 }
00398
00399 void StringPlugin::SetUnits(QString units)
00400 {
00401 if (units == "pixels")
00402 {
00403 units_ = PIXELS;
00404 }
00405 else if (units == "percent")
00406 {
00407 units_ = PERCENT;
00408 }
00409 }
00410
00411 void StringPlugin::SetOffsetX(int offset)
00412 {
00413 offset_x_ = offset;
00414 }
00415
00416 void StringPlugin::SetOffsetY(int offset)
00417 {
00418 offset_y_ = offset;
00419 }
00420
00421 void StringPlugin::stringCallback(const std_msgs::StringConstPtr& str)
00422 {
00423 message_.setText(QString(str->data.c_str()));
00424 message_.prepare(QTransform(), font_);
00425
00426 has_message_ = true;
00427 has_painted_ = false;
00428 initialized_ = true;
00429 }
00430
00431 std::string StringPlugin::AnchorToString(StringPlugin::Anchor anchor)
00432 {
00433 std::string anchor_string = "top left";
00434
00435 if (anchor == TOP_LEFT)
00436 {
00437 anchor_string = "top left";
00438 }
00439 else if (anchor == TOP_CENTER)
00440 {
00441 anchor_string = "top center";
00442 }
00443 else if (anchor == TOP_RIGHT)
00444 {
00445 anchor_string = "top right";
00446 }
00447 else if (anchor == CENTER_LEFT)
00448 {
00449 anchor_string = "center left";
00450 }
00451 else if (anchor == CENTER)
00452 {
00453 anchor_string = "center";
00454 }
00455 else if (anchor == CENTER_RIGHT)
00456 {
00457 anchor_string = "center right";
00458 }
00459 else if (anchor == BOTTOM_LEFT)
00460 {
00461 anchor_string = "bottom left";
00462 }
00463 else if (anchor == BOTTOM_CENTER)
00464 {
00465 anchor_string = "bottom center";
00466 }
00467 else if (anchor == BOTTOM_RIGHT)
00468 {
00469 anchor_string = "bottom right";
00470 }
00471
00472 return anchor_string;
00473 }
00474
00475 std::string StringPlugin::UnitsToString(StringPlugin::Units units)
00476 {
00477 std::string units_string = "pixels";
00478
00479 if (units == PIXELS)
00480 {
00481 units_string = "pixels";
00482 }
00483 else if (units == PERCENT)
00484 {
00485 units_string = "percent";
00486 }
00487
00488 return units_string;
00489 }
00490 }