当前位置: 首页 > news >正文

rviz是如何获取图像里选择的点云的3D坐标的

以前以为rviz是用OpenGL渲染绘图,那么获取图像里像素点对应的真实3D坐标是采用的OpenGL里提供的API实现的,结果一看代码还真不是这样,rviz也就渲染用了OpenGL,其他都是自己实现的,图像界面的实现完全是遵循MVC设计模式自己实现的透视投影和坐标转换等所有相关类。获取点云图像里所选择的点云点的3D坐标相关的代码是这里:

src/rviz/selection/selection_manager.cpp:bool SelectionManager::getPatchDepthImage(Ogre::Viewport* viewport,int x,int y,unsigned width,unsigned height,std::vector<float>& depth_vector)
{unsigned int num_pixels = width * height;depth_vector.reserve(num_pixels);setDepthTextureSize(width, height);M_CollisionObjectToSelectionHandler::iterator handler_it = objects_.begin();M_CollisionObjectToSelectionHandler::iterator handler_end = objects_.end();for (; handler_it != handler_end; ++handler_it){handler_it->second->preRenderPass(0);}if (render(viewport, depth_render_texture_, x, y, x + width, y + height, depth_pixel_box_, "Depth",depth_texture_width_, depth_texture_height_)){uint8_t* data_ptr = (uint8_t*)depth_pixel_box_.data;for (uint32_t pixel = 0; pixel < num_pixels; ++pixel){uint8_t a = data_ptr[4 * pixel];uint8_t b = data_ptr[4 * pixel + 1];uint8_t c = data_ptr[4 * pixel + 2];int int_depth = (c << 16) | (b << 8) | a;float normalized_depth = ((float)int_depth) / (float)0xffffff;depth_vector.push_back(normalized_depth * camera_->getFarClipDistance());}}else{ROS_WARN("Failed to render depth patch\n");return false;}handler_it = objects_.begin();handler_end = objects_.end();for (; handler_it != handler_end; ++handler_it){handler_it->second->postRenderPass(0);}return true;
}bool SelectionManager::get3DPatch(Ogre::Viewport* viewport,int x,int y,unsigned width,unsigned height,bool skip_missing,std::vector<Ogre::Vector3>& result_points)
{boost::recursive_mutex::scoped_lock lock(global_mutex_);ROS_DEBUG("SelectionManager.get3DPatch()");std::vector<float> depth_vector;if (!getPatchDepthImage(viewport, x, y, width, height, depth_vector))return false;unsigned int pixel_counter = 0;Ogre::Matrix4 projection = camera_->getProjectionMatrix();float depth;for (unsigned y_iter = 0; y_iter < height; ++y_iter)for (unsigned x_iter = 0; x_iter < width; ++x_iter){depth = depth_vector[pixel_counter];// Deal with missing or invalid pointsif ((depth > camera_->getFarClipDistance()) || (depth == 0)){++pixel_counter;if (!skip_missing){result_points.push_back(Ogre::Vector3(NAN, NAN, NAN));}continue;}Ogre::Vector3 result_point;// We want to shoot rays through the center of pixels, not the corners,// so add .5 pixels to the x and y coordinate to get to the center// instead of the top left of the pixel.Ogre::Real screenx = float(x_iter + .5) / float(width);Ogre::Real screeny = float(y_iter + .5) / float(height);if (projection[3][3] == 0.0) // If this is a perspective projection{// get world-space ray from camera & mouse coordOgre::Ray vp_ray = camera_->getCameraToViewportRay(screenx, screeny);// transform ray direction back into camera coordsOgre::Vector3 dir_cam = camera_->getDerivedOrientation().Inverse() * vp_ray.getDirection();// normalize, so dir_cam.z == -depthdir_cam = dir_cam / dir_cam.z * depth * -1;// compute 3d point from camera origin and direction*/result_point = camera_->getDerivedPosition() + camera_->getDerivedOrientation() * dir_cam;}else // else this must be an orthographic projection.{// For orthographic projection, getCameraToViewportRay() does// the right thing for us, and the above math does not work.Ogre::Ray ray;camera_->getCameraToViewportRay(screenx, screeny, &ray);result_point = ray.getPoint(depth);}result_points.push_back(result_point);++pixel_counter;}return !result_points.empty();
}bool SelectionManager::get3DPoint(Ogre::Viewport* viewport, int x, int y, Ogre::Vector3& result_point)
{ROS_DEBUG("SelectionManager.get3DPoint()");std::vector<Ogre::Vector3> result_points_temp;bool success = get3DPatch(viewport, x, y, 1, 1, true, result_points_temp);if (result_points_temp.empty()){// return result_point unmodified if get point fails.return false;}result_point = result_points_temp[0];return success;
}

世界3D坐标是用的射线法计算出来。SelectionManager::get3DPoint()被rviz里多个地方调用,凡是UI界面上需要查看点的坐标地方都是调用它。

http://www.lryc.cn/news/233300.html

相关文章:

  • 响应体和状态码
  • CNN进展:AlexNet、VGGNet、ResNet 和 Inception
  • 数据的存储--MongoDB文档存储
  • Notepad++ 通过HexEditor插件查看.hprof文件、heap dump文件的堆转储数据
  • 微服务学习 | Eureka注册中心
  • spring boot集成quartz
  • [Linux] yum仓库相关
  • 2023.11.15-hivesql之炸裂函数explode练习
  • Linux - 内核 - 安全机制 - 内存页表安全
  • Linux---(七)Makefile写进度条(三个版本)
  • 数据库分页查询
  • 如何选择合适的数据库管理工具?Navicat Or DBeaver
  • Opencv!!在树莓派上安装Opencv!
  • 三菱FX3U小项目—传输带定分级控制
  • 实例解释遇到前端报错时如何排查问题
  • 微电影分销付费短剧小程序开发
  • 时间序列预测中的4大类8种异常值检测方法(从根源上提高预测精度)
  • Android---Gradle 构建问题解析
  • 02-2解析JsonPath
  • Git拉取远程指定分支
  • 使用Ant Design Pro开发时的一个快速开发接口请求的技巧
  • m1 rvm install 3.0.0 Error running ‘__rvm_make -j8‘
  • 对产品实现汇率换算服务(将两个CompletableFuture对象整合起来,无论它们是否存在依赖)
  • 数据库期末考前复习题(单选+多选+判断+解答)
  • Ubuntu22.04源码安装ROS-noetic(ROS1非ROS2),编译运行VINS-MONO
  • 窗口管理工具 Mosaic mac中文版功能特点
  • Sql Prompt 10下载安装图文教程
  • VB.net webbrowser 自定义下载接口实现
  • Android 启动优化案例-WebView非预期初始化排查
  • 【MATLAB源码-第80期】基于蚯蚓优化算法(EOA)的无人机三维路径规划,输出做短路径图和适应度曲线