赞
踩
大家好呀,我是一个SLAM方向的在读博士,深知SLAM学习过程一路走来的坎坷,也十分感谢各位大佬的优质文章和源码。随着知识的越来越多,越来越细,我准备整理一个自己的激光SLAM学习笔记专栏,从0带大家快速上手激光SLAM,也方便想入门SLAM的同学和小白学习参考,相信看完会有一定的收获。如有不对的地方欢迎指出,欢迎各位大佬交流讨论,一起进步。 博主创建了一个科研互助群Q:772356582,欢迎大家加入讨论。
目录
ROS很重要一点就是可以对不同类型的消息进行接收与发送,并且能够对数据进行实时的可视化,ROS官网已经给出了很多的消息类型供我们使用。
std_msgs是一种标准消息类型包,包含了一些常用的基本数据类型的消息定义。
std_msgs/Bool:表示布尔值(True或False)
std_msgs/Int8、Int16、Int32、Int64:表示有符号的8、16、32和64位整数
std_msgs/UInt8、UInt16、UInt32、UInt64:表示无符号的8、16、32和64位整数
std_msgs/Float32、Float64:表示单精度和双精度浮点数
std_msgs/String:表示字符串
std_msgs还包括其他类型的消息,例如:
std_msgs/Time:表示ROS的时间戳
std_msgs/Duration:表示时间段
std_msgs/Header:表示ROS消息头,其中包括时间戳、坐标系和序列号等信息。
发布接收字符串
- #include "ros/ros.h"
- #include "std_msgs/String.h"
- #include "std_msgs/Int32.h"
-
- void callback_string(const std_msgs::String::ConstPtr& msg)
- {
- ROS_INFO("Received string: %s", msg->data.c_str());
- // 创建一个新的std_msgs::String类型消息
- std_msgs::String output_msg;
- output_msg.data = "Received string: " + msg->data;
- // 发布新消息
- pub.publish(output_msg);
- }
-
-
- void callback_int(const std_msgs::Int32::ConstPtr& msg)
- {
- ROS_INFO("Received integer: %d", msg->data);
- // 创建一个新的std_msgs::String类型消息
- std_msgs::String output_msg;
- output_msg.data = "Received integer: " + std::to_string(msg->data);
- // 发布新消息
- pub.publish(output_msg);
- }
-
- int main(int argc, char **argv)
- {
- // 初始化ROS节点
- ros::init(argc, argv, "listener_and_talker");
- // 创建ROS节点句柄和两个订阅节点对象,以及一个发布者对象
- ros::NodeHandle nh;
- ros::Subscriber sub_string = nh.subscribe("my_topic_string", 10, callback_string);
- ros::Subscriber sub_int = nh.subscribe("my_topic_int", 10, callback_int);
- ros::Publisher pub = nh.advertise<std_msgs::String>("my_topic_output", 10);
- // 运行ROS节点
- ros::spin();
- return 0;
-
- }

ROS中的geometry_msgs是一个包含了各种几何形状相关的消息类型的软件包,主要用于机器人运动控制和感知相关应用中。
更多使用方法见官网https://wiki.ros.org/geometry_msgs?distro=melodic
- 发布接收位置
- #include <ros/ros.h>
- #include <geometry_msgs/PoseStamped.h>
-
- void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg)
- {
- // 在回调函数中处理接收到的消息
- ROS_INFO("Received a pose at time %f", msg->header.stamp.toSec());
- ROS_INFO("Position: x=%f, y=%f, z=%f", msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);
- ROS_INFO("Orientation: x=%f, y=%f, z=%f, w=%f", msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z, msg->pose.orientation.w);
- }
-
- int main(int argc, char **argv)
- {
- ros::init(argc, argv, "pose_node"); // 初始化ROS节点
- ros::NodeHandle nh;
-
- // 创建一个用于接收pose消息的订阅者
- ros::Subscriber sub = nh.subscribe<geometry_msgs::PoseStamped>("pose_topic", 10, poseCallback);
-
- // 创建一个用于发送pose消息的发布者
- ros::Publisher pub = nh.advertise<geometry_msgs::PoseStamped>("pose_topic", 10);
-
- // 设置消息的头部信息
- geometry_msgs::PoseStamped pose_msg;
- pose_msg.header.stamp = ros::Time::now();
- pose_msg.header.frame_id = "map";
-
- // 设置消息的内容
- pose_msg.pose.position.x = 1.0;
- pose_msg.pose.position.y = 2.0;
- pose_msg.pose.position.z = 3.0;
- pose_msg.pose.orientation.x = 0.0;
- pose_msg.pose.orientation.y = 0.0;
- pose_msg.pose.orientation.z = 0.0;
- pose_msg.pose.orientation.w = 1.0;
-
- // 发布消息
- pub.publish(pose_msg);
- ros::spin();
- return 0;
- }

ROS中的sensor_msgs是一种消息类型,用于在ROS节点之间传输与传感器数据相关的消息。sensor_msgs包含了许多常用传感器的消息类型,例如激光雷达、相机、IMU、GPS等。
发布接收点云
- #include <ros/ros.h>
- #include <sensor_msgs/PointCloud2.h>
-
- void pointCloudCallback(const sensor_msgs::PointCloud2ConstPtr& input_cloud_msg)
-
- {
- // TODO: 这里添加处理输入点云的代码
- // 将处理后的点云发布到 /output_pointcloud 话题上
- pub.publish(output_cloud_msg);
- }
-
-
-
- int main(int argc, char** argv)
-
- {
- ros::init(argc, argv, "point_cloud_node");
- ros::NodeHandle nh;
- // 订阅 /input_pointcloud 话题上的点云消息
- ros::Subscriber sub = nh.subscribe<sensor_msgs::PointCloud2>("/input_pointcloud", 1, pointCloudCallback);
- // 发布处理后的点云消息到 /output_pointcloud 话题上
- ros::Publisher pub = nh.advertise<sensor_msgs::PointCloud2>("/output_pointcloud", 1);
- ros::spin();
- return 0;
- }

ROS中的shape_msgs是一个定义了常见几何形状(例如点,线,多边形,立方体等)的ROS消息类型。它是ROS的标准消息之一,常用于描述机器人的形状和姿态,以及环境中的障碍物等。shape_msgs消息并不能直接在rviz中可视化,需要将其转换为visualization_msgs/Marker消息才能在rviz中显示。而visualization_msgs/Marker消息则可以直接在rviz中可视化,并且提供了多种不同的可视化方式,例如用线、面、箭头等方式显示几何形状。
发送三角形顶点坐标
- #include <ros/ros.h>
- #include <shape_msgs/Polygon.h>
- #include <geometry_msgs/Point32.h>
-
-
- int main(int argc, char **argv)
-
- {
- // 初始化ROS节点
- ros::init(argc, argv, "polygon_publisher");
- // 创建节点句柄
- ros::NodeHandle nh;
- // 创建一个publisher发布名为"/polygon"的shape_msgs/Polygon消息
- ros::Publisher polygon_pub = nh.advertise<shape_msgs::Polygon>("/polygon", 10);
- // 设置消息发布频率
- ros::Rate loop_rate(10);
- while (ros::ok())
- {
- // 创建shape_msgs/Polygon消息并填充数据
- shape_msgs::Polygon polygon;
- geometry_msgs::Point32 p1, p2, p3;
- p1.x = 0.0;
- p1.y = 0.0;
- p1.z = 0.0;
- p2.x = 1.0;
- p2.y = 0.0;
- p2.z = 0.0;
- p3.x = 0.0;
- p3.y = 1.0;
- p3.z = 0.0;
- polygon.points.push_back(p1);
- polygon.points.push_back(p2);
- polygon.points.push_back(p3);
-
- // 发布消息
- polygon_pub.publish(polygon);
- // 按照指定频率循环发布消息
- loop_rate.sleep();
- }
- return 0;
-
- }

接收三角形顶点坐标
- #include <ros/ros.h>
- #include <shape_msgs/Polygon.h>
- #include <geometry_msgs/Point32.h>
-
- void polygonCallback(const shape_msgs::Polygon::ConstPtr& msg)
- {
- // 输出消息内容
- ROS_INFO("Received polygon message:");
- for (int i = 0; i < msg->points.size(); i++)
- {
-
- ROS_INFO("Point %d: (%f, %f, %f)", i+1, msg->points[i].x, msg->points[i].y, msg->points[i].z);
- }
- }
-
- int main(int argc, char **argv)
- {
- // 初始化ROS节点
- ros::init(argc, argv, "polygon_subscriber");
- // 创建节点句柄
- ros::NodeHandle nh;
- // 创建一个subscriber订阅名为"/polygon"的shape_msgs/Polygon消息
- ros::Subscriber polygon_sub = nh.subscribe("/polygon", 10, polygonCallback);
- // 循环处理回调函数
- ros::spin();
- return 0;
- }

trajectory_msgs 是一个ROS消息包,包含用于描述机器人或其它物体运动的消息类型。其主要包含以下消息类型:
发布者周期性地创建一个 JointTrajectory 消息并发布到话题 joint_trajectory 上,而订阅者则通过回调函数 jointTrajectoryCallback 接收到这些消息并打印出其中的关节信息。
- #include <ros/ros.h>
- #include <trajectory_msgs/JointTrajectory.h>
- #include <trajectory_msgs/JointTrajectoryPoint.h>
-
- int main(int argc, char **argv)
- {
- ros::init(argc, argv, "joint_trajectory_publisher_subscriber");
- ros::NodeHandle nh;
- // 创建一个发布者,用于发布机器人的关节轨迹
- ros::Publisher joint_trajectory_pub = nh.advertise<trajectory_msgs::JointTrajectory>("joint_trajectory", 10);
- // 创建一个订阅者,用于接收机器人的关节轨迹
- ros::Subscriber joint_trajectory_sub = nh.subscribe("joint_trajectory", 10, jointTrajectoryCallback);
- ros::Rate loop_rate(10); // 发布频率为10Hz
- while (ros::ok())
- {
- // 创建一个JointTrajectory消息
- trajectory_msgs::JointTrajectory trajectory_msg;
- trajectory_msg.header.stamp = ros::Time::now();
- trajectory_msg.joint_names.push_back("joint_1");
- trajectory_msg.joint_names.push_back("joint_2");
- trajectory_msg.joint_names.push_back("joint_3");
-
- // 创建一个JointTrajectoryPoint消息
- trajectory_msgs::JointTrajectoryPoint point_msg;
- point_msg.positions.push_back(0.5);
- point_msg.positions.push_back(0.5);
- point_msg.positions.push_back(0.5);
- point_msg.velocities.push_back(0.0);
- point_msg.velocities.push_back(0.0);
- point_msg.velocities.push_back(0.0);
- point_msg.time_from_start = ros::Duration(1.0); // 在1秒的时间内到达目标位置
- trajectory_msg.points.push_back(point_msg); // 将JointTrajectoryPoint添加到JointTrajectory中
- // 发布JointTrajectory消息
- joint_trajectory_pub.publish(trajectory_msg);
- ros::spinOnce();
- loop_rate.sleep();
- }
- return 0;
- }
-
- // 订阅者回调函数,用于接收机器人的关节轨迹
- void jointTrajectoryCallback(const trajectory_msgs::JointTrajectory& msg)
- {
- ROS_INFO("Received JointTrajectory message");
- // 打印出轨迹中的关节信息
- for (int i = 0; i < msg.joint_names.size(); i++)
- {
- ROS_INFO("%s position: %f, velocity: %f, acceleration: %f",
- msg.joint_names[i].c_str(),
- msg.points[0].positions[i],
- msg.points[0].velocities[i],
- msg.points[0].accelerations[i]);
- }
-
- }

ROS中的nav_msgs是一组与导航相关的消息(messages)和服务(services)类型的软件包。它包含了一些用于导航任务的标准消息格式,比如机器人当前的位姿信息、目标点、障碍物等信息。
发布接收一个Path,Path可以直接在RVIZ可视化
- #include <ros/ros.h>
- #include <nav_msgs/Path.h>
-
- int main(int argc, char** argv)
- {
- // 初始化ROS节点
- ros::init(argc, argv, "path_publisher");
- ros::NodeHandle nh;
- // 创建一个发布者,发布类型为nav_msgs::Path,话题名为/path
- ros::Publisher path_pub = nh.advertise<nav_msgs::Path>("path", 10);
- // 创建一个订阅者,订阅类型为nav_msgs::Path,话题名为/path
- ros::Subscriber path_sub = nh.subscribe<nav_msgs::Path>("path", 10, pathCallback);
-
-
- // 循环发布消息
- ros::Rate loop_rate(10);
- while (ros::ok())
- {
- // 创建一个新的Path消息
- nav_msgs::Path path_msg;
- // 将路径信息添加到Path消息中,此处省略具体代码
- ...
- // 发布Path消息
- path_pub.publish(path_msg);
- // 循环等待
- ros::spinOnce();
- loop_rate.sleep();
- }
- return 0;
- }
-
-
-
- // 接收到Path消息时的回调函数
- void pathCallback(const nav_msgs::Path::ConstPtr& path_msg)
- {
- // 处理接收到的Path消息,此处省略具体代码
- ...
- }

visualization_msgs是ROS中的一个用于可视化的消息类型软件包。它包含了一些用于在ROS中进行可视化的标准消息格式,如点、线、箭头、网格、文字、标记等。
https://wiki.ros.org/visualization_msgs?distro=melodic
- *发布接收
- 发布Marker消息
- ros::Publisher vis_pub = nh.advertise<visualization_msgs::Marker>( "visualization_marker", 0, markerCallback);
- 接收Marker消息
- ros::Subscriber sub = nh.subscribe<visualization_msgs::Marker>("marker_topic", 10, markerCallback);
- *消息内容
- //基本信息
- visualization_msgs::Marker marker;
- marker.header.frame_id = "base_link";
- marker.header.stamp = ros::Time();
- marker.ns = "my_namespace";
- marker.id = 0;
- marker.type = visualization_msgs::Marker::SPHERE;//确定类型
- marker.action = visualization_msgs::Marker::ADD;
- //位置信息
- marker.pose.position.x = 1;
- marker.pose.position.y = 1;
- marker.pose.position.z = 1;
- marker.pose.orientation.x = 0.0;
- marker.pose.orientation.y = 0.0;
- marker.pose.orientation.z = 0.0;
- marker.pose.orientation.w = 1.0;
- //Marker范围
- marker.scale.x = 1;
- marker.scale.y = 0.1;
- marker.scale.z = 0.1;
- //Marker颜色
- marker.color.a = 1.0; // Don't forget to set the alpha!
- marker.color.r = 0.0;
- marker.color.g = 1.0;
- marker.color.b = 0.0;
- //加载地图
- marker.mesh_resource="package://pr2_description/meshes/base_v0/base.dae";
- //发布消息
- vis_pub.publish( marker );

建立一个箭头
- #include <ros/ros.h>
- #include <visualization_msgs/Marker.h>
-
- int main( int argc, char** argv )
- {
- ros::init(argc, argv, "basic_shapes");
- ros::NodeHandle n;
- ros::Rate r(1);
- ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);
-
- while (ros::ok())
- {
- visualization_msgs::Marker marker;
- marker.header.frame_id = "base_link";
- marker.header.stamp = ros::Time::now();
- marker.ns = "basic_shapes";
- marker.id = 0;
- marker.type = visualization_msgs::Marker::ARROW;
- marker.action = visualization_msgs::Marker::ADD;
-
- marker.scale.x = 1.0;
- marker.scale.y = 0.1;
- marker.scale.z = 0.1;
-
- marker.color.r = 1.0f;
- marker.color.g = 0.0f;
- marker.color.b = 0.0f;
- marker.color.a = 1.0;
-
- marker.pose.position.x = 0;
- marker.pose.position.y = 0;
- marker.pose.position.z = 0;
-
- marker.pose.orientation.x = 0.0;
- marker.pose.orientation.y = 0.0;
- marker.pose.orientation.z = 0.0;
- marker.pose.orientation.w = 1.0;
-
- marker_pub.publish(marker);
-
- r.sleep();
- }
- }

建立一个cube list
- #include <ros/ros.h>
- #include <visualization_msgs/Marker.h>
- int main( int argc, char** argv )
- {
- ros::init(argc, argv, "basic_shapes");
- ros::NodeHandle n;
- ros::Rate r(1);
- ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);
-
- visualization_msgs::Marker marker;
- marker.header.frame_id = "base_link";
- marker.header.stamp = ros::Time::now();
- marker.ns = "basic_shapes";
- marker.type = visualization_msgs::Marker::CUBE_LIST;
- marker.action = visualization_msgs::Marker::ADD;
-
- marker.scale.x = 0.1;
- marker.scale.y = 0.1;
- marker.scale.z = 0.1;
-
- marker.color.r = 0.0f;
- marker.color.g = 1.0f;
- marker.color.b = 0.0f;
- marker.color.a = 1.0;
-
- for (int i = 0; i < 10; i++)
- {
- for (int j = 0; j < 10; j++)
- {
- for (int k = 0; k < 10; k++)
- {
- geometry_msgs::Point cube_point;
- cube_point.x = i * 0.1;
- cube_point.y = j * 0.1;
- cube_point.z = k * 0.1;
-
- marker.points.push_back(cube_point);
- }
- }
- }
-
- while (ros::ok())
- {
- marker_pub.publish(marker);
- r.sleep();
- }
- }

jsk_recognition_msgs 是一个ROS消息包,它包含了一些用于机器人视觉和感知的常用消息类型。这些消息类型可以被用于在ROS系统中传递机器人感知和识别结果。
主要包含以下消息类型:
- 自定义发送
- #include <ros/ros.h>
- #include <jsk_recognition_msgs/BoundingBoxArray.h>
- #include <jsk_recognition_msgs/BoundingBox.h>
-
- int main(int argc, char** argv)
- {
- ros::init(argc, argv, "custom_bounding_box_array_publisher");
- ros::NodeHandle nh;
-
- // 创建一个 BoundingBoxArray 发布者
- ros::Publisher bb_array_pub = nh.advertise<jsk_recognition_msgs::BoundingBoxArray>("bounding_box_array_topic", 10);
-
- // 创建一个 BoundingBoxArray 消息
- jsk_recognition_msgs::BoundingBoxArray bb_array_msg;
-
- // 设置 BoundingBoxArray 消息的 Header
- bb_array_msg.header.frame_id = "base_link";
- bb_array_msg.header.stamp = ros::Time::now();
-
- // 创建一个 BoundingBox 消息并添加到 BoundingBoxArray 消息中
- jsk_recognition_msgs::BoundingBox bb_msg;
- bb_msg.header = bb_array_msg.header;
- bb_msg.label = "object_1"; // 设置标签
- bb_msg.pose.position.x = 1.0; // 设置位置坐标
- bb_msg.pose.position.y = 2.0;
- bb_msg.pose.position.z = 3.0;
- bb_msg.dimensions.x = 0.5; // 设置尺寸
- bb_msg.dimensions.y = 0.3;
- bb_msg.dimensions.z = 0.2;
- bb_array_msg.boxes.push_back(bb_msg); // 将 BoundingBox 消息添加到 BoundingBoxArray 中
-
- // 发布 BoundingBoxArray 消息
- bb_array_pub.publish(bb_array_msg);
-
- ROS_INFO("Custom BoundingBoxArray published");
-
- ros::spin();
- return 0;
- }
-
- 接收获取坐标
- #include <ros/ros.h>
- #include <jsk_recognition_msgs/BoundingBoxArray.h>
-
- void boundingBoxCallback(const jsk_recognition_msgs::BoundingBoxArray::ConstPtr& msg) {
- // 遍历BoundingBoxArray中的所有BoundingBox
- for (const auto& bbox : msg->boxes) {
- // 获取BoundingBox的尺寸
- const auto& dimensions = bbox.dimensions;
- float width = dimensions.x;
- float height = dimensions.y;
- float depth = dimensions.z;
-
- // 获取BoundingBox的坐标
- const auto& position = bbox.pose.position;
- float x = position.x;
- float y = position.y;
- float z = position.z;
-
- // 在控制台输出BoundingBox的尺寸和坐标
- ROS_INFO_STREAM("Bounding Box Dimensions (width, height, depth): " << width << ", " << height << ", " << depth);
- ROS_INFO_STREAM("Bounding Box Position (x, y, z): " << x << ", " << y << ", " << z);
- }
- }
-
- int main(int argc, char** argv) {
- // 初始化ROS节点
- ros::init(argc, argv, "bounding_box_subscriber");
-
- // 创建节点句柄
- ros::NodeHandle nh;
-
- // 订阅jsk_recognition_msgs::BoundingBoxArray消息
- ros::Subscriber sub = nh.subscribe<jsk_recognition_msgs::BoundingBoxArray>("bounding_box_topic", 1000, boundingBoxCallback);
-
- // 循环等待回调函数
- ros::spin();
-
- return 0;
- }

在上面的代码中,我们定义了一个回调函数 boundingBoxCallback() 来处理接收到的 jsk_recognition_msgs::BoundingBoxArray 消息。在这个回调函数中,我们遍历 BoundingBoxArray 中的所有 BoundingBox,并从每个 BoundingBox 中获取其尺寸和坐标信息。具体来说,我们使用 bbox.dimensions 来获取 BoundingBox 的尺寸,使用 bbox.pose.position 来获取 BoundingBox 的位置。最后,我们在控制台上输出每个 BoundingBox 的尺寸和坐标信息,以便我们可以在程序运行时检查它们。
到此,专栏的ROS讲解部分结束,你应该知道ROS能干啥和编写简单的发送接收消息的代码了,下一步我们将介绍SLAM的理论基础。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。