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 #include <mapviz_plugins/robot_image_plugin.h>
00031
00032
00033 #include <cstdio>
00034 #include <algorithm>
00035 #include <vector>
00036
00037
00038 #include <QGLWidget>
00039 #include <QPalette>
00040 #include <QImage>
00041 #include <QFileDialog>
00042
00043
00044 #include <ros/master.h>
00045
00046 #include <mapviz/select_frame_dialog.h>
00047
00048
00049 #include <pluginlib/class_list_macros.h>
00050 PLUGINLIB_DECLARE_CLASS(
00051 mapviz_plugins,
00052 robot_image,
00053 mapviz_plugins::RobotImagePlugin,
00054 mapviz::MapvizPlugin);
00055
00056 namespace mapviz_plugins
00057 {
00058 RobotImagePlugin::RobotImagePlugin() :
00059 config_widget_(new QWidget()),
00060 width_(1),
00061 height_(1),
00062 texture_loaded_(false),
00063 transformed_(false)
00064 {
00065 ui_.setupUi(config_widget_);
00066
00067
00068 QPalette p(config_widget_->palette());
00069 p.setColor(QPalette::Background, Qt::white);
00070 config_widget_->setPalette(p);
00071
00072
00073 QPalette p3(ui_.status->palette());
00074 p3.setColor(QPalette::Text, Qt::red);
00075 ui_.status->setPalette(p3);
00076
00077 UpdateShape();
00078
00079 QObject::connect(ui_.browse, SIGNAL(clicked()), this, SLOT(SelectFile()));
00080 QObject::connect(ui_.selectframe, SIGNAL(clicked()), this, SLOT(SelectFrame()));
00081 QObject::connect(ui_.frame, SIGNAL(editingFinished()), this, SLOT(FrameEdited()));
00082 QObject::connect(ui_.width, SIGNAL(valueChanged(double)), this, SLOT(WidthChanged(double)));
00083 QObject::connect(ui_.height, SIGNAL(valueChanged(double)), this, SLOT(HeightChanged(double)));
00084 }
00085
00086 RobotImagePlugin::~RobotImagePlugin()
00087 {
00088 }
00089
00090 void RobotImagePlugin::SelectFile()
00091 {
00092 QFileDialog dialog(config_widget_, "Select PNG Image");
00093 dialog.setFileMode(QFileDialog::ExistingFile);
00094 dialog.setNameFilter(tr("PNG Image Files (*.png)"));
00095
00096 dialog.exec();
00097
00098 if (dialog.result() == QDialog::Accepted && dialog.selectedFiles().count() == 1)
00099 {
00100 ui_.image->setText(dialog.selectedFiles().first());
00101 filename_ = dialog.selectedFiles().first().toStdString();
00102 LoadImage();
00103 }
00104 }
00105
00106 void RobotImagePlugin::SelectFrame()
00107 {
00108 std::string frame = mapviz::SelectFrameDialog::selectFrame(tf_);
00109 if (!frame.empty())
00110 {
00111 ui_.frame->setText(QString::fromStdString(frame));
00112 FrameEdited();
00113 }
00114 }
00115
00116 void RobotImagePlugin::FrameEdited()
00117 {
00118 source_frame_ = ui_.frame->text().toStdString();
00119 PrintWarning("Waiting for transform.");
00120
00121 ROS_INFO("Setting target frame to to %s", source_frame_.c_str());
00122
00123 initialized_ = true;
00124
00125 UpdateShape();
00126 }
00127
00128 void RobotImagePlugin::WidthChanged(double value)
00129 {
00130 width_ = value;
00131
00132 UpdateShape();
00133 }
00134
00135 void RobotImagePlugin::HeightChanged(double value)
00136 {
00137 height_ = value;
00138
00139 UpdateShape();
00140 }
00141
00142 void RobotImagePlugin::UpdateShape()
00143 {
00144 top_left_ = tf::Point(-width_ / 2.0, height_ / 2.0, 0);
00145 top_right_ = tf::Point(width_ / 2.0, height_ / 2.0, 0);
00146 bottom_left_ = tf::Point(-width_ / 2.0, -height_/2.0, 0);
00147 bottom_right_ = tf::Point(width_ / 2.0, -height_ / 2.0, 0);
00148 }
00149
00150 void RobotImagePlugin::PrintError(const std::string& message)
00151 {
00152 if (message == ui_.status->text().toStdString())
00153 {
00154 return;
00155 }
00156
00157 ROS_ERROR("Error: %s", message.c_str());
00158 QPalette p(ui_.status->palette());
00159 p.setColor(QPalette::Text, Qt::red);
00160 ui_.status->setPalette(p);
00161 ui_.status->setText(message.c_str());
00162 }
00163
00164 void RobotImagePlugin::PrintInfo(const std::string& message)
00165 {
00166 if (message == ui_.status->text().toStdString())
00167 {
00168 return;
00169 }
00170
00171 ROS_INFO("%s", message.c_str());
00172 QPalette p(ui_.status->palette());
00173 p.setColor(QPalette::Text, Qt::green);
00174 ui_.status->setPalette(p);
00175 ui_.status->setText(message.c_str());
00176 }
00177
00178 void RobotImagePlugin::PrintWarning(const std::string& message)
00179 {
00180 if (message == ui_.status->text().toStdString())
00181 {
00182 return;
00183 }
00184
00185 ROS_WARN("%s", message.c_str());
00186 QPalette p(ui_.status->palette());
00187 p.setColor(QPalette::Text, Qt::darkYellow);
00188 ui_.status->setPalette(p);
00189 ui_.status->setText(message.c_str());
00190 }
00191
00192 QWidget* RobotImagePlugin::GetConfigWidget(QWidget* parent)
00193 {
00194 config_widget_->setParent(parent);
00195
00196 return config_widget_;
00197 }
00198
00199 bool RobotImagePlugin::Initialize(QGLWidget* canvas)
00200 {
00201 canvas_ = canvas;
00202
00203 return true;
00204 }
00205
00206 void RobotImagePlugin::Draw(double x, double y, double scale)
00207 {
00208 if (texture_loaded_ && transformed_)
00209 {
00210 glColor3f(1.0f, 1.0f, 1.0f);
00211 glEnable(GL_TEXTURE_2D);
00212 glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(texture_id_));
00213
00214 glBegin(GL_QUADS);
00215
00216
00217 glTexCoord2f(0, 1); glVertex2d(top_left_transformed_.x(), top_left_transformed_.y());
00218 glTexCoord2f(1, 1); glVertex2d(top_right_transformed_.x(), top_right_transformed_.y());
00219 glTexCoord2f(1, 0); glVertex2d(bottom_right_transformed_.x(), bottom_right_transformed_.y());
00220 glTexCoord2f(0, 0); glVertex2d(bottom_left_transformed_.x(), bottom_left_transformed_.y());
00221
00222 glEnd();
00223
00224 glDisable(GL_TEXTURE_2D);
00225
00226 PrintInfo("OK");
00227 }
00228 }
00229
00230 void RobotImagePlugin::Transform()
00231 {
00232 transformed_ = false;
00233
00234 swri_transform_util::Transform transform;
00235 if (GetTransform(ros::Time(), transform))
00236 {
00237 top_left_transformed_ = transform * top_left_;
00238 top_right_transformed_ = transform * top_right_;
00239 bottom_left_transformed_ = transform * bottom_left_;
00240 bottom_right_transformed_ = transform * bottom_right_;
00241 transformed_ = true;
00242 }
00243 else
00244 {
00245 PrintError("No transform between " + source_frame_ + " and " + target_frame_);
00246 }
00247 }
00248
00249 void RobotImagePlugin::LoadImage()
00250 {
00251 ROS_INFO("Loading image");
00252 try
00253 {
00254 QImage nullImage;
00255 image_ = nullImage;
00256
00257 if (texture_loaded_)
00258 {
00259 GLuint ids[1];
00260 ids[0] = static_cast<GLuint>(texture_id_);
00261 glDeleteTextures(1, &ids[0]);
00262 texture_loaded_ = false;
00263 }
00264
00265 if (image_.load(filename_.c_str()))
00266 {
00267 int width = image_.width();
00268 int height = image_.height();
00269
00270 float max_dim = std::max(width, height);
00271 dimension_ = static_cast<int>(std::pow(2, std::ceil(std::log(max_dim) / std::log(2.0f))));
00272
00273 if (width != dimension_ || height != dimension_)
00274 {
00275 image_ = image_.scaled(dimension_, dimension_, Qt::IgnoreAspectRatio, Qt::FastTransformation);
00276 }
00277
00278 image_ = QGLWidget::convertToGLFormat(image_);
00279
00280 GLuint ids[1];
00281 glGenTextures(1, &ids[0]);
00282 texture_id_ = ids[0];
00283
00284 glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(texture_id_));
00285 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dimension_, dimension_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_.bits());
00286
00287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00289
00290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00292
00293 texture_loaded_ = true;
00294 }
00295 else
00296 {
00297 PrintError("Failed to load image.");
00298 }
00299 }
00300 catch (const std::exception& e)
00301 {
00302 PrintError("Failed to load image. Exception occured.");
00303 }
00304 }
00305
00306 void RobotImagePlugin::LoadConfig(const YAML::Node& node, const std::string& path)
00307 {
00308 if (node["frame"])
00309 {
00310 node["frame"] >> source_frame_;
00311 ui_.frame->setText(source_frame_.c_str());
00312 }
00313
00314 if (node["image"])
00315 {
00316 node["image"] >> filename_;
00317 ui_.image->setText(filename_.c_str());
00318 }
00319
00320 if (node["width"])
00321 {
00322 node["width"] >> width_;
00323 ui_.width->setValue(width_);
00324 }
00325
00326 if (node["height"])
00327 {
00328 node["height"] >> height_;
00329 ui_.height->setValue(height_);
00330 }
00331
00332 UpdateShape();
00333 LoadImage();
00334 FrameEdited();
00335 }
00336
00337 void RobotImagePlugin::SaveConfig(YAML::Emitter& emitter, const std::string& path)
00338 {
00339 emitter << YAML::Key << "frame" << YAML::Value << ui_.frame->text().toStdString();
00340 emitter << YAML::Key << "image" << YAML::Value << ui_.image->text().toStdString();
00341 emitter << YAML::Key << "width" << YAML::Value << width_;
00342 emitter << YAML::Key << "height" << YAML::Value << height_;
00343 }
00344 }
00345