ipa_coverage_planning 算法解读(一)


avatar
GuoYulong 2024-07-17 274

ipa_room_segmentation (地图分割,用于房间分区)

客户端 room_segmentation_client.cpp

头文件

#include <ros/ros.h> 
// 提供了ROS节点的基本功能,如初始化节点、发布和订阅消息等。

#include <ros/package.h> 
// 提供了与ROS包管理相关的功能,例如获取包路径。

#include <string>
#include <vector>
// C++标准库的头文件,用于处理字符串和向量数据结构。

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
// OpenCV库的头文件,用于图像处理和图形用户界面功能。

#include <cv_bridge/cv_bridge.h>
// cv_bridge库的一部分,它提供了ROS图像消息和OpenCV图像格式之间转换的功能

#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
// actionlib库的头文件,用于实现ROS中的动作服务器和客户端

#include <ipa_building_msgs/MapSegmentationAction.h>
// 房间分割任务相关的自定义消息类型和服务

#include <ipa_room_segmentation/dynamic_reconfigure_client.h>
// 动态重新配置房间分割服务的客户端接口

main
客户端是直接把测试地图名写入一个 vector 变量 map_names 中,然后在 for 循环中在指定地址获取相应的地图地址,把地图转为地图话题数据,再装入 goal 中发送给服务端。

设置Ros环境并创建一个节点,一边程序可以与Ros网络中的其他节点进行交互

ros::init(argc, argv, "room_segmentation_client");
ros::NodeHandle nh;

添加地图表,每一个都是对应文件中的地图图像文件名

// map names
std::vector< std::string > map_names;
map_names.push_back("lab_ipa");
map_names.push_back("lab_c_scan");
...

整个函数围绕这个for循环进行

for (size_t image_index = 0; image_index<map_names.size(); ++image_index) {
    // 在 ipa_room_segmentation 功能包的指定位置搜索地图
    std::string image_filename = ros::package::getPath("ipa_room_segmentation") + "/common/files/test_maps/" + map_names[image_index] + ".png";
    cv::Mat map = cv::imread(image_filename.c_str(), 0); // cv 读地图
    ...
    cv_image.toImageMsg(labeling); // 数据转换
    actionlib::SimpleActionClient<ipa_building_msgs::MapSegmentationAction> ac("room_segmentation_server", true);
    ... // goal 数据装包
    ac.sendGoal(goal); // 目标发送到服务端
    bool finished_before_timeout = ac.waitForResult(ros::Duration()); // 等待结果
 
    if (finished_before_timeout) {
      ... // 数据转换到 cv 格式
      cv::imshow("segmentation", colour_segmented_map); // cv 显示地图
      cv::waitKey(); // 敲空格测试下一张地图
    }
  }

详细解释for中的代码

这段代码展示了如何在ROS(Robot Operating System)中使用OpenCV库来导入图像文件。具体来说,它是从一个特定的路径加载图像文件到cv::Mat对象中

// import maps
std::string image_filename = ros::package::getPath("ipa_room_segmentation") + "/common/files/test_maps/" + map_names[image_index] + ".png";
cv::Mat map = cv::imread(image_filename.c_str(), 0);

二值化,将图像中小于255的全部设置为0,即非白即黑

for (int y = 0; y < map.rows; y++)
{
	for (int x = 0; x < map.cols; x++)
	{
		//find not reachable regions and make them black
		if (map.at<unsigned char>(y, x) < 250)
		{
			map.at<unsigned char>(y, x) = 0;
		}
		//else make it white
		else
		{
			map.at<unsigned char>(y, x) = 255;
		}
	}
}

这段代码展示了如何使用cv_bridge库将OpenCV的图像格式转换为ROS的sensor_msgs::Image消息格式


//声明了一个sensor_msgs::Image类型的变量labeling,这是ROS中用于表示图像的标准消息类型。
sensor_msgs::Image labeling;

//声明了一个cv_bridge::CvImage类型的变量cv_image。CvImage是cv_bridge中的一个类,用于在ROS消息和OpenCV图像之间进行转换
cv_bridge::CvImage cv_image;

//这行代码被注释掉了,但如果取消注释,它会设置cv_image的时间戳为当前时间
//cv_image.header.stamp = ros::Time::now();

//设置cv_image的编码格式为"mono8",这表示图像是以8位单通道(灰度)格式存储的。
cv_image.encoding = "mono8";

//将OpenCV图像map赋值给cv_image的image成员。这里的map是一个cv::Mat类型的变量,包含了要转换的图像数据。
cv_image.image = map;

//这个函数调用将cv_image中的OpenCV图像转换为ROS的sensor_msgs::Image消息,并将结果存储在labeling变量中。
cv_image.toImageMsg(labeling);

相关阅读

注意!!!

新增会员中心页面,方便管理个人账户,充值功能暂不开启,请勿为本网站进行任何充值活动!!!

通知!!!

① 过年好!!!拖更几个月了已经,年后继续更新!!