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
00032
00033
00034
00035
00036 #include <rviz/uniform_string_stream.h>
00037 #include "camera_info_display.h"
00038 #include <OGRE/OgreMaterialManager.h>
00039 #include <OGRE/OgreMaterial.h>
00040 #include <OGRE/OgreBlendMode.h>
00041 #include <QImage>
00042 #include <OGRE/OgreHardwarePixelBuffer.h>
00043
00044 namespace jsk_rviz_plugins
00045 {
00046 TrianglePolygon::TrianglePolygon(
00047 Ogre::SceneManager* manager,
00048 Ogre::SceneNode* node,
00049 const cv::Point3d& O,
00050 const cv::Point3d& A,
00051 const cv::Point3d& B,
00052 const std::string& name,
00053 const Ogre::ColourValue& color,
00054 bool use_color,
00055 bool upper_triangle)
00056 {
00057
00058
00059 manual_ = manager->createManualObject();
00060 manual_->clear();
00061 manual_->begin(name,
00062 Ogre::RenderOperation::OT_TRIANGLE_STRIP);
00063 manual_->position(O.x, O.y, O.z);
00064 if (upper_triangle) {
00065 manual_->textureCoord(0, 0);
00066 }
00067 else {
00068 manual_->textureCoord(1, 0);
00069 }
00070 if (use_color) {
00071 manual_->colour(color);
00072 }
00073 manual_->position(A.x, A.y, A.z);
00074 if (upper_triangle) {
00075 manual_->textureCoord(1, 0);
00076 }
00077 else {
00078 manual_->textureCoord(1, 1);
00079 }
00080 if (use_color) {
00081 manual_->colour(color);
00082 }
00083 manual_->position(B.x, B.y, B.z);
00084 if (upper_triangle) {
00085 manual_->textureCoord(0, 1);
00086 }
00087 else {
00088 manual_->textureCoord(0, 1);
00089 }
00090 if (use_color) {
00091 manual_->colour(color);
00092 }
00093 manual_->end();
00094 node->attachObject(manual_);
00095 }
00096
00097 TrianglePolygon::~TrianglePolygon()
00098 {
00099 manual_->detachFromParent();
00100
00101 }
00102
00103 CameraInfoDisplay::CameraInfoDisplay(): image_updated_(true)
00104 {
00106
00108 far_clip_distance_property_ = new rviz::FloatProperty(
00109 "far clip",
00110 1.0,
00111 "far clip distance from the origin of camera info",
00112 this, SLOT(updateFarClipDistance()));
00113 show_edges_property_ = new rviz::BoolProperty(
00114 "show edges",
00115 true,
00116 "show edges of the region of the camera info",
00117 this, SLOT(updateShowEdges()));
00118 show_polygons_property_ = new rviz::BoolProperty(
00119 "show polygons",
00120 true,
00121 "show polygons of the region of the camera info",
00122 this, SLOT(updateShowPolygons()));
00123 not_show_side_polygons_property_ = new rviz::BoolProperty(
00124 "not show side polygons",
00125 true,
00126 "do not show polygons of the region of the camera info",
00127 this, SLOT(updateNotShowSidePolygons()));
00128 use_image_property_ = new rviz::BoolProperty(
00129 "use image",
00130 false,
00131 "use image as texture",
00132 this, SLOT(updateUseImage()));
00133 image_topic_property_ = new rviz::RosTopicProperty(
00134 "Image Topic", "",
00135 ros::message_traits::datatype<sensor_msgs::Image>(),
00136 "sensor_msgs::Image topic to subscribe to.",
00137 this, SLOT( updateImageTopic() ));
00138 color_property_ = new rviz::ColorProperty(
00139 "color",
00140 QColor(85, 255, 255),
00141 "color of CameraInfo",
00142 this, SLOT(updateColor()));
00143 edge_color_property_ = new rviz::ColorProperty(
00144 "edge color",
00145 QColor(125, 125, 125),
00146 "edge color of CameraInfo",
00147 this, SLOT(updateEdgeColor()));
00148 alpha_property_ = new rviz::FloatProperty(
00149 "alpha",
00150 0.5,
00151 "alpha blending value",
00152 this, SLOT(updateAlpha()));
00153 }
00154
00155 CameraInfoDisplay::~CameraInfoDisplay()
00156 {
00157 if (edges_) {
00158 edges_->clear();
00159 }
00160 polygons_.clear();
00161 delete far_clip_distance_property_;
00162 delete color_property_;
00163 delete alpha_property_;
00164 delete show_polygons_property_;
00165 delete edge_color_property_;
00166 }
00167
00168 void CameraInfoDisplay::reset()
00169 {
00170 MFDClass::reset();
00171 if (edges_) {
00172 edges_->clear();
00173 }
00174 polygons_.clear();
00175 camera_info_ = sensor_msgs::CameraInfo::ConstPtr();
00176 }
00177
00178 void CameraInfoDisplay::onInitialize()
00179 {
00180 MFDClass::onInitialize();
00181 scene_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00182 updateColor();
00183 updateAlpha();
00184 updateFarClipDistance();
00185 updateShowPolygons();
00186 updateNotShowSidePolygons();
00187 updateShowEdges();
00188 updateImageTopic();
00189 updateUseImage();
00190 updateEdgeColor();
00191 }
00192
00193 void CameraInfoDisplay::processMessage(
00194 const sensor_msgs::CameraInfo::ConstPtr& msg)
00195 {
00196 if (!isSameCameraInfo(msg)) {
00197 createCameraInfoShapes(msg);
00198 }
00199
00200 Ogre::Vector3 position;
00201 Ogre::Quaternion quaternion;
00202 if(!context_->getFrameManager()->getTransform(msg->header.frame_id,
00203 msg->header.stamp,
00204 position,
00205 quaternion)) {
00206 ROS_ERROR( "Error transforming pose '%s' from frame '%s' to frame '%s'",
00207 qPrintable( getName() ), msg->header.frame_id.c_str(),
00208 qPrintable( fixed_frame_ ));
00209 }
00210 scene_node_->setPosition(position);
00211 scene_node_->setOrientation(quaternion);
00212 camera_info_ = msg;
00213 }
00214
00215 void CameraInfoDisplay::update(float wall_dt, float ros_dt)
00216 {
00217 boost::mutex::scoped_lock lock(mutex_);
00218 if (image_updated_) {
00219 ROS_DEBUG("image updated");
00220 if (!bottom_texture_.isNull()) {
00221 drawImageTexture();
00222 image_updated_ = false;
00223 }
00224 }
00225 }
00226
00227 bool CameraInfoDisplay::isSameCameraInfo(
00228 const sensor_msgs::CameraInfo::ConstPtr& msg)
00229 {
00230 if (camera_info_) {
00231 bool meta_same_p =
00232 msg->header.frame_id == camera_info_->header.frame_id &&
00233 msg->height == camera_info_->height &&
00234 msg->width == camera_info_->width &&
00235 msg->distortion_model == camera_info_->distortion_model;
00236 if (meta_same_p) {
00237 for (size_t i = 0; i < msg->P.size(); i++) {
00238 if (msg->P[i] != camera_info_->P[i]) {
00239 return false;
00240 }
00241 }
00242 return true;
00243 }
00244 else {
00245 return false;
00246 }
00247 }
00248 else {
00249 return false;
00250 }
00251 }
00252
00253 void CameraInfoDisplay::addPointToEdge(
00254 const cv::Point3d& point)
00255 {
00256 Ogre::Vector3 p;
00257 p[0] = point.x;
00258 p[1] = point.y;
00259 p[2] = point.z;
00260 edges_->addPoint(p);
00261 }
00262
00263 void CameraInfoDisplay::addPolygon(
00264 const cv::Point3d& O, const cv::Point3d& A, const cv::Point3d& B, std::string name, bool use_color, bool upper_triangle)
00265 {
00266 Ogre::ColourValue color = rviz::qtToOgre(color_);
00267 color.a = alpha_;
00268 TrianglePolygon::Ptr triangle (new TrianglePolygon(
00269 scene_manager_,
00270 scene_node_,
00271 O, A, B, name,
00272 color,
00273 use_color,
00274 upper_triangle));
00275 polygons_.push_back(triangle);
00276 }
00277
00278 void CameraInfoDisplay::createTextureForBottom(int width, int height)
00279 {
00280 ROS_INFO("%dx%d", width, height);
00281 if (bottom_texture_.isNull()
00282 || bottom_texture_->getWidth() != width
00283 || bottom_texture_->getHeight() != height) {
00284 static uint32_t count = 0;
00285 rviz::UniformStringStream ss;
00286 ss << "CameraInfoDisplayPolygonBottom" << count++;
00287 material_bottom_
00288 = Ogre::MaterialManager::getSingleton().create(
00289 ss.str(),
00290 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00291 bottom_texture_ = Ogre::TextureManager::getSingleton().createManual(
00292 material_bottom_->getName() + "Texture",
00293 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
00294 Ogre::TEX_TYPE_2D, width, height, 0, Ogre::PF_A8R8G8B8, Ogre::TU_DEFAULT);
00295 material_bottom_->getTechnique(0)->getPass(0)->setColourWriteEnabled(true);
00296 Ogre::ColourValue color = rviz::qtToOgre(color_);
00297 color.a = alpha_;
00298 material_bottom_->getTechnique(0)->getPass(0)->setAmbient(color);
00299 material_bottom_->setReceiveShadows(false);
00300 material_bottom_->getTechnique(0)->setLightingEnabled(true);
00301 material_bottom_->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);
00302 material_bottom_->getTechnique(0)->getPass(0)->setLightingEnabled(false);
00303 material_bottom_->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
00304 material_bottom_->getTechnique(0)->getPass(0)->setDepthCheckEnabled(true);
00305
00306 material_bottom_->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_DIFFUSE);
00307 material_bottom_->getTechnique(0)->getPass(0)->createTextureUnitState(bottom_texture_->getName());
00308 material_bottom_->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00309 }
00310 }
00311
00312 void CameraInfoDisplay::prepareMaterial()
00313 {
00314 if (texture_.isNull()) {
00315
00316 static uint32_t count = 0;
00317 rviz::UniformStringStream ss;
00318 ss << "CameraInfoDisplayPolygon" << count++;
00319 material_
00320 = Ogre::MaterialManager::getSingleton().create(
00321 ss.str(),
00322 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
00323 texture_ = Ogre::TextureManager::getSingleton().createManual(
00324 material_->getName() + "Texture",
00325 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
00326 Ogre::TEX_TYPE_2D, 1, 1, 0, Ogre::PF_A8R8G8B8, Ogre::TU_DEFAULT);
00327 material_->getTechnique(0)->getPass(0)->setColourWriteEnabled(true);
00328 Ogre::ColourValue color = rviz::qtToOgre(color_);
00329 color.a = alpha_;
00330 material_->getTechnique(0)->getPass(0)->setAmbient(color);
00331 material_->setReceiveShadows(false);
00332 material_->getTechnique(0)->setLightingEnabled(true);
00333 material_->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);
00334 material_->getTechnique(0)->getPass(0)->setLightingEnabled(false);
00335 material_->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
00336 material_->getTechnique(0)->getPass(0)->setDepthCheckEnabled(true);
00337
00338 material_->getTechnique(0)->getPass(0)->setVertexColourTracking(Ogre::TVC_DIFFUSE);
00339 material_->getTechnique(0)->getPass(0)->createTextureUnitState(texture_->getName());
00340 material_->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
00341 createTextureForBottom(640, 480);
00342 }
00343 }
00344
00345 void CameraInfoDisplay::subscribeImage(std::string topic)
00346 {
00347
00348 image_sub_.shutdown();
00349 if (topic.empty()) {
00350 ROS_WARN("topic name is empty");
00351 }
00352 ros::NodeHandle nh;
00353 image_sub_ = nh.subscribe(topic, 1,
00354 &CameraInfoDisplay::imageCallback, this);
00355 }
00356
00357 void CameraInfoDisplay::drawImageTexture()
00358 {
00359 bottom_texture_->getBuffer()->lock( Ogre::HardwareBuffer::HBL_NORMAL );
00360 const Ogre::PixelBox& pixelBox
00361 = bottom_texture_->getBuffer()->getCurrentLock();
00362 Ogre::uint8* pDest = static_cast<Ogre::uint8*> (pixelBox.data);
00363 memset(pDest, 0, bottom_texture_->getWidth() * bottom_texture_->getHeight());
00364 QImage Hud(pDest, bottom_texture_->getWidth(), bottom_texture_->getHeight(), QImage::Format_ARGB32 );
00365 for (size_t j = 0; j < bottom_texture_->getHeight(); j++) {
00366 for (size_t i = 0; i < bottom_texture_->getWidth(); i++) {
00367 if (use_image_ && !image_.empty() &&
00368 bottom_texture_->getHeight() == image_.rows &&
00369 bottom_texture_->getWidth() == image_.cols) {
00370 ROS_DEBUG("bottom_texture_->getHeight(): %lu", bottom_texture_->getHeight());
00371 ROS_DEBUG("bottom_texture_->getWidth(): %lu", bottom_texture_->getWidth());
00372 ROS_DEBUG("image_.rows: %d", image_.rows);
00373 ROS_DEBUG("image_.cols: %d", image_.cols);
00374 QColor color(image_.data[j * image_.step + i * image_.elemSize() + 0],
00375 image_.data[j * image_.step + i * image_.elemSize() + 1],
00376 image_.data[j * image_.step + i * image_.elemSize() + 2],
00377 alpha_ * 255.0);
00378 Hud.setPixel(i, j, color.rgba());
00379 }
00380 else {
00381 Hud.setPixel(i, j, color_.rgba());
00382 }
00383 }
00384 }
00385 bottom_texture_->getBuffer()->unlock();
00386 }
00387
00388
00389 void CameraInfoDisplay::imageCallback(
00390 const sensor_msgs::Image::ConstPtr& msg)
00391 {
00392 boost::mutex::scoped_lock lock(mutex_);
00393 cv_bridge::CvImagePtr cv_ptr;
00394 try
00395 {
00396 cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::RGB8);
00397 image_ = cv_ptr->image;
00398
00399 if (bottom_texture_.isNull()
00400 || bottom_texture_->getWidth() != image_.cols
00401 || bottom_texture_->getHeight() != image_.rows) {
00402 createTextureForBottom(image_.cols, image_.rows);
00403 if (camera_info_) {
00404 createCameraInfoShapes(camera_info_);
00405 }
00406 }
00407 image_updated_ = true;
00408 }
00409 catch (cv_bridge::Exception& e)
00410 {
00411 ROS_ERROR("cv_bridge exception: %s", e.what());
00412 }
00413 }
00414
00415 void CameraInfoDisplay::createCameraInfoShapes(
00416 const sensor_msgs::CameraInfo::ConstPtr& msg)
00417 {
00418 polygons_.clear();
00419 if (edges_) {
00420 edges_->clear();
00421 }
00422 image_geometry::PinholeCameraModel model;
00423 bool model_success_p = model.fromCameraInfo(msg);
00424 if (!model_success_p) {
00425 ROS_ERROR("failed to create camera model");
00426 return;
00427 }
00428
00430
00432 if (!edges_) {
00433 edges_.reset(new rviz::BillboardLine(context_->getSceneManager(),
00434 scene_node_));
00435 edges_->setLineWidth(0.01);
00436 }
00437
00438 cv::Point2d a(0, 0), b(msg->width, 0),
00439 c(msg->width, msg->height), d(0, msg->height);
00440
00441 cv::Point3d A = model.projectPixelTo3dRay(a);
00442 cv::Point3d B = model.projectPixelTo3dRay(b);
00443 cv::Point3d C = model.projectPixelTo3dRay(c);
00444 cv::Point3d D = model.projectPixelTo3dRay(d);
00445
00446 cv::Point3d scaled_A = A * far_clip_distance_;
00447 cv::Point3d scaled_B = B * far_clip_distance_;
00448 cv::Point3d scaled_C = C * far_clip_distance_;
00449 cv::Point3d scaled_D = D * far_clip_distance_;
00450
00451 cv::Point3d O(0, 0, 0);
00452
00454
00456 if (show_polygons_) {
00458
00460 Ogre::ColourValue color = rviz::qtToOgre(color_);
00461 color.a = alpha_;
00462 prepareMaterial();
00463 if (!not_show_side_polygons_) {
00464 material_->getTechnique(0)->getPass(0)->setAmbient(color);
00465 {
00466 texture_->getBuffer()->lock( Ogre::HardwareBuffer::HBL_NORMAL );
00467 const Ogre::PixelBox& pixelBox
00468 = texture_->getBuffer()->getCurrentLock();
00469 Ogre::uint8* pDest = static_cast<Ogre::uint8*> (pixelBox.data);
00470 memset(pDest, 0, 1);
00471 QImage Hud(pDest, 1, 1, QImage::Format_ARGB32 );
00472 Hud.setPixel(0, 0, color_.rgba());
00473 texture_->getBuffer()->unlock();
00474 }
00475 addPolygon(O, scaled_B, scaled_A, material_->getName(), true, true);
00476 addPolygon(O, scaled_C, scaled_B, material_->getName(), true, true);
00477 addPolygon(O, scaled_D, scaled_C, material_->getName(), true, true);
00478 addPolygon(O, scaled_A, scaled_D, material_->getName(), true, true);
00479 }
00480
00481 drawImageTexture();
00482
00483 addPolygon(scaled_A, scaled_B, scaled_D, material_bottom_->getName(), false, true);
00484 addPolygon(scaled_B, scaled_C, scaled_D, material_bottom_->getName(), false, false);
00485 }
00487
00489 if (show_edges_) {
00490 edges_->clear();
00491 edges_->setMaxPointsPerLine(2);
00492 edges_->setNumLines(8);
00493 edges_->setColor(edge_color_.red() / 255.0,
00494 edge_color_.green() / 255.0,
00495 edge_color_.blue() / 255.0,
00496 alpha_);
00497 addPointToEdge(O); addPointToEdge(scaled_A); edges_->newLine();
00498 addPointToEdge(O); addPointToEdge(scaled_B); edges_->newLine();
00499 addPointToEdge(O); addPointToEdge(scaled_C); edges_->newLine();
00500 addPointToEdge(O); addPointToEdge(scaled_D); edges_->newLine();
00501 addPointToEdge(scaled_A); addPointToEdge(scaled_B); edges_->newLine();
00502 addPointToEdge(scaled_B); addPointToEdge(scaled_C); edges_->newLine();
00503 addPointToEdge(scaled_C); addPointToEdge(scaled_D); edges_->newLine();
00504 addPointToEdge(scaled_D); addPointToEdge(scaled_A);
00505 }
00506 }
00507
00509
00511 void CameraInfoDisplay::updateColor()
00512 {
00513 color_ = color_property_->getColor();
00514 if (camera_info_) {
00515 createCameraInfoShapes(camera_info_);
00516 }
00517 }
00518
00519 void CameraInfoDisplay::updateEdgeColor()
00520 {
00521 edge_color_ = edge_color_property_->getColor();
00522 if (camera_info_) {
00523 createCameraInfoShapes(camera_info_);
00524 }
00525 }
00526
00527 void CameraInfoDisplay::updateAlpha()
00528 {
00529 alpha_ = alpha_property_->getFloat();
00530 if (camera_info_) {
00531 createCameraInfoShapes(camera_info_);
00532 }
00533 }
00534
00535 void CameraInfoDisplay::updateFarClipDistance()
00536 {
00537 far_clip_distance_ = far_clip_distance_property_->getFloat();
00538 if (camera_info_) {
00539 createCameraInfoShapes(camera_info_);
00540 }
00541 }
00542
00543 void CameraInfoDisplay::updateShowPolygons()
00544 {
00545 show_polygons_ = show_polygons_property_->getBool();
00546 if (camera_info_) {
00547 createCameraInfoShapes(camera_info_);
00548 }
00549 }
00550
00551 void CameraInfoDisplay::updateShowEdges()
00552 {
00553 show_edges_ = show_edges_property_->getBool();
00554 if (camera_info_) {
00555 createCameraInfoShapes(camera_info_);
00556 }
00557 }
00558
00559 void CameraInfoDisplay::updateImageTopic()
00560 {
00561 if (use_image_) {
00562 std::string topic = image_topic_property_->getStdString();
00563 subscribeImage(topic);
00564 }
00565 }
00566
00567 void CameraInfoDisplay::updateUseImage()
00568 {
00569 use_image_ = use_image_property_->getBool();
00570 updateImageTopic();
00571 }
00572 void CameraInfoDisplay::updateNotShowSidePolygons()
00573 {
00574 not_show_side_polygons_ = not_show_side_polygons_property_->getBool();
00575 if (camera_info_) {
00576 createCameraInfoShapes(camera_info_);
00577 }
00578 }
00579 }
00580
00581
00582 #include <pluginlib/class_list_macros.h>
00583 PLUGINLIB_EXPORT_CLASS( jsk_rviz_plugins::CameraInfoDisplay, rviz::Display )