Robot Operating System——点云数据
大纲
- 应用场景
- sensor_msgs::msg::PointCloud
- 定义
- 字段解释
- 案例
- sensor_msgs::msg::PointCloud2
- 定义
- 字段解释
- sensor_msgs::msg::PointField
- 定义
- 字段解释
- 案例
sensor_msgs::msg::PointCloud和sensor_msgs::msg::PointCloud2 是 ROS (Robot Operating System) 中的一个消息类型,用于表示点云数据。点云数据是由多个点组成的集合,每个点包含三维空间中的位置和其他属性(如强度)。
sensor_msgs::msg::PointCloud2 与 sensor_msgs::msg::PointCloud 相比,PointCloud2 提供了更灵活和高效的点云数据表示方式,支持更多的点属性和更大的数据量。
应用场景
- 环境感知
- 三维建模:点云数据可以用于创建环境的三维模型。通过激光雷达、深度相机等传感器获取的点云数据,可以重建环境的三维结构,广泛应用于机器人导航、自动驾驶等领域。
- 障碍物检测:点云数据可以用于检测和识别环境中的障碍物。通过分析点云数据,可以识别出障碍物的位置和形状,帮助机器人或自动驾驶车辆避开障碍物。
- 自动驾驶
- 道路检测:在自动驾驶系统中,点云数据可以用于检测道路边界、车道线和其他道路特征。通过处理点云数据,可以提取出道路的几何信息,帮助车辆在道路上安全行驶。
- 物体识别:点云数据可以用于识别和分类道路上的物体,如行人、车辆、交通标志等。通过分析点云数据,可以识别出不同类型的物体,提高自动驾驶系统的感知能力。
- 机器人导航
- 地图构建:在机器人导航系统中,点云数据可以用于构建环境地图。通过累积多帧点云数据,可以创建出详细的环境地图,帮助机器人进行自主导航。
- 路径规划:点云数据可以用于路径规划。通过分析点云数据,可以识别出可行驶区域和障碍物,规划出最优的行驶路径。
- 无人机
- 地形跟踪:在无人机系统中,点云数据可以用于地形跟踪。通过分析点云数据,可以获取地形的三维信息,帮助无人机在复杂地形中飞行。
- 避障飞行:点云数据可以用于避障飞行。通过检测和识别空中的障碍物,可以规划出安全的飞行路径,避免碰撞。
- 工业自动化
- 质量检测:在工业自动化中,点云数据可以用于产品的质量检测。通过分析点云数据,可以检测出产品的几何缺陷,提高生产质量。
- 机器人抓取:点云数据可以用于机器人抓取任务。通过分析点云数据,可以识别出物体的位置和形状,规划出最佳的抓取姿态。
sensor_msgs::msg::PointCloud
定义
namespace sensor_msgs
{
namespace msg
{struct PointCloud
{std_msgs::msg::Header header;std::vector<geometry_msgs::msg::Point32> points;std::vector<sensor_msgs::msg::ChannelFloat32> channels;
};} // namespace msg
} // namespace sensor_msgs
字段解释
- header:消息头,包含时间戳和坐标系信息。
- points:点云中的点的数组,每个点包含三维坐标(x, y, z)。
- channels:每个点的附加属性的数组,如强度、颜色等。
案例
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/point_cloud.hpp"
#include "geometry_msgs/msg/point32.hpp"
#include "sensor_msgs/msg/channel_float32.hpp"class PointCloudPublisher : public rclcpp::Node
{
public:PointCloudPublisher(): Node("point_cloud_publisher"){publisher_ = this->create_publisher<sensor_msgs::msg::PointCloud>("point_cloud", 10);timer_ = this->create_wall_timer(500ms, std::bind(&PointCloudPublisher::publish_point_cloud, this));}private:void publish_point_cloud(){auto message = sensor_msgs::msg::PointCloud();message.header.stamp = this->now();message.header.frame_id = "map";geometry_msgs::msg::Point32 point;point.x = 1.0;point.y = 2.0;point.z = 3.0;message.points.push_back(point);sensor_msgs::msg::ChannelFloat32 channel;channel.name = "intensity";channel.values.push_back(0.5);message.channels.push_back(channel);RCLCPP_INFO(this->get_logger(), "Publishing point cloud data");publisher_->publish(message);}rclcpp::Publisher<sensor_msgs::msg::PointCloud>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<PointCloudPublisher>());rclcpp::shutdown();return 0;
}
sensor_msgs::msg::PointCloud2
定义
namespace sensor_msgs
{
namespace msg
{struct PointCloud2
{std_msgs::msg::Header header;uint32_t height;uint32_t width;std::vector<sensor_msgs::msg::PointField> fields;bool is_bigendian;uint32_t point_step;uint32_t row_step;std::vector<uint8_t> data;bool is_dense;
};} // namespace msg
} // namespace sensor_msgs
字段解释
- header:消息头,包含时间戳和坐标系信息。
- height:点云的高度(如果是 2D 点云,则为 1)。
- width:点云的宽度(点的数量)。
- fields:点云中每个点的字段描述,如 x, y, z, intensity 等。
- is_bigendian:数据是否是大端序。
- point_step:每个点的字节数。
- row_step:每行的字节数(对于 2D 点云)。
- data:实际的点云数据,按字节存储。
- is_dense:如果点云中没有无效点,则为 true。
sensor_msgs::msg::PointField
定义
namespace sensor_msgs
{
namespace msg
{struct PointField
{std::string name;uint32_t offset;uint8_t datatype;uint32_t count;// Constants for datatypestatic const uint8_t INT8 = 1;static const uint8_t UINT8 = 2;static const uint8_t INT16 = 3;static const uint8_t UINT16 = 4;static const uint8_t INT32 = 5;static const uint8_t UINT32 = 6;static const uint8_t FLOAT32 = 7;static const uint8_t FLOAT64 = 8;
};} // namespace msg
} // namespace sensor_msgs
字段解释
- name:字段名称,如 “x”, “y”, “z”, “intensity” 等。
- offset:字段在点数据结构中的偏移量(以字节为单位)。
- datatype:字段的数据类型,可以是以下之一:
- INT8:8 位有符号整数
- UINT8:8 位无符号整数
- INT16:16 位有符号整数
- UINT16:16 位无符号整数
- INT32:32 位有符号整数
- UINT32:32 位无符号整数
- FLOAT32:32 位浮点数
- FLOAT64:64 位浮点数
- count:字段的元素数量(通常为 1)。
案例
#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/point_cloud2.hpp"
#include "sensor_msgs/msg/point_field.hpp"
#include "std_msgs/msg/header.hpp"class PointCloud2Publisher : public rclcpp::Node
{
public:PointCloud2Publisher(): Node("point_cloud2_publisher"){publisher_ = this->create_publisher<sensor_msgs::msg::PointCloud2>("point_cloud2", 10);timer_ = this->create_wall_timer(500ms, std::bind(&PointCloud2Publisher::publish_point_cloud, this));}private:void publish_point_cloud(){auto message = sensor_msgs::msg::PointCloud2();message.header.stamp = this->now();message.header.frame_id = "map";message.height = 1;message.width = 1;sensor_msgs::msg::PointField field;field.name = "x";field.offset = 0;field.datatype = sensor_msgs::msg::PointField::FLOAT32;field.count = 1;message.fields.push_back(field);field.name = "y";field.offset = 4;field.datatype = sensor_msgs::msg::PointField::FLOAT32;field.count = 1;message.fields.push_back(field);field.name = "z";field.offset = 8;field.datatype = sensor_msgs::msg::PointField::FLOAT32;field.count = 1;message.fields.push_back(field);message.is_bigendian = false;message.point_step = 12;message.row_step = message.point_step * message.width;message.is_dense = true;message.data.resize(message.row_step * message.height);float * data_ptr = reinterpret_cast<float *>(message.data.data());data_ptr[0] = 1.0; // xdata_ptr[1] = 2.0; // ydata_ptr[2] = 3.0; // zRCLCPP_INFO(this->get_logger(), "Publishing point cloud2 data");publisher_->publish(message);}rclcpp::Publisher<sensor_msgs::msg::PointCloud2>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<PointCloud2Publisher>());rclcpp::shutdown();return 0;
}
