如何将点云移至RVIZ原点?tf2坐标变换方案遇阻求助
点云移至原点的ROS实现问题
我是ROS新手,现有一个点云文件,将其发布为话题后,通过另一个节点订阅并修改后重新发布,流程正常。但在RVIZ中可视化时,点云未处于原点,而是位于平台边缘。我希望能简单地将点云移至原点。
目前我尝试使用tf2包解决,试图将object_frame转换到map帧(期望点云在map原点),但未成功。想请教:该方案是否为最优最简方案?若是,我遗漏了什么?
回调函数代码
geometry_msgs::msg::TransformStamped transform; transform.header.stamp = this->get_clock()->now(); transform.header.frame_id = "object_frame"; transform.child_frame_id = "map"; // Set the position of the object relative to the Rviz frame transform.transform.translation.x = 0.0; transform.transform.translation.y = 0.0; transform.transform.translation.z = 0.0; // Set the orientation of the object relative to the Rviz frame transform.transform.rotation.x = 0.0; transform.transform.rotation.y = 0.0; transform.transform.rotation.z = 0.0; transform.transform.rotation.w = 1.0; tf_broadcaster->sendTransform(transform);
发布函数代码
void Preprocessor::publish_pointcloud_supervoxel() { // Convert the PointCloud to a PointCloud2 message auto pcl_msg_supervoxel = std::make_shared<sensor_msgs::msg::PointCloud2>(); //sensor_msgs::msg::PointCloud2 pcl_msg_supervoxel; pcl::toROSMsg(*colored_supervoxel_cloud, *pcl_msg_supervoxel); //pcl_msg_supervoxel->width = adjacent_supervoxel_centers.size(); pcl_msg_supervoxel->header.frame_id = "map"; pcl_msg_supervoxel->header.stamp = this->get_clock()->now(); // Publish the message supervoxel_publisher->publish(*pcl_msg_supervoxel); }
解答
方案是否最优?
用TF变换不是最简方案。因为你已经将发布的点云frame_id直接设为map,此时直接修改点云数据的坐标,让所有点的XYZ减去偏移量(比如点云的质心坐标),就能直接让点云落在map原点,步骤更直接,不需要维护额外的TF变换关系。
若坚持用TF方案,你的代码错误在哪?
你的TF变换逻辑完全搞反了:
- 你想要表达的是object_frame相对于map的位置(原点),但代码中
header.frame_id = "object_frame"、child_frame_id = "map",这相当于告诉TF树:map是object_frame的子帧,和实际需求相反。 - 正确的TF变换写法应该是:
另外,这个TF变换只对transform.header.frame_id = "map"; transform.child_frame_id = "object_frame"; // 平移旋转参数不变,因为要让object_frame在map的原点frame_id为object_frame的点云生效,但你发布的点云frame_id已经是map,所以这个TF对你的点云没有任何作用——点云直接挂在map帧下,TF不会修改它的显示位置。
最简实现方法:直接修改点云坐标
在发布点云前,计算点云的质心(或偏移量),然后将所有点的坐标减去这个值,就能让点云移动到原点:
void Preprocessor::publish_pointcloud_supervoxel() { // 计算点云质心 Eigen::Vector4f centroid; pcl::compute3DCentroid(*colored_supervoxel_cloud, centroid); // 平移点云到原点 pcl::PointCloud<pcl::PointXYZRGB>::Ptr shifted_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); for (const auto& point : *colored_supervoxel_cloud) { pcl::PointXYZRGB shifted_point; shifted_point.x = point.x - centroid[0]; shifted_point.y = point.y - centroid[1]; shifted_point.z = point.z - centroid[2]; shifted_point.r = point.r; shifted_point.g = point.g; shifted_point.b = point.b; shifted_cloud->push_back(shifted_point); } // 转换为ROS消息并发布 auto pcl_msg_supervoxel = std::make_shared<sensor_msgs::msg::PointCloud2>(); pcl::toROSMsg(*shifted_cloud, *pcl_msg_supervoxel); pcl_msg_supervoxel->header.frame_id = "map"; pcl_msg_supervoxel->header.stamp = this->get_clock()->now(); supervoxel_publisher->publish(*pcl_msg_supervoxel); }
内容的提问来源于stack exchange,提问作者eren
相关产品推荐
相关产品推荐

