> 文章列表 > ROS开发之如何在同一个节点订阅、处理、发布消息?

ROS开发之如何在同一个节点订阅、处理、发布消息?

ROS开发之如何在同一个节点订阅、处理、发布消息?

文章目录

  • 0、引言
  • 1、创建中间特殊文件(含订阅者和发布者)
  • 2、在CMakeLists.txt添加编译规则
  • 3、在launch添加启动项
  • 4、编译运行
  • 5、三维显示

0、引言

  在ROS应用一般会用到发布者和订阅者,若只接收传感器数据,则只实现订阅者就行,但有时需要订阅者部分做简单数据处理后,再发布出去,供其他订阅者接收。以上场景涉及一个中间文件,即既是订阅者,也是发布者的文件,本文查阅现有网络资源,复现现有实现方法,在树莓派中利用二维雷达传感器数据实现数据的订阅,做三维处理后发布,并在上位机虚拟机显示三维点云。相较于【ROS开发之如何将RPLidar数据在RViz中三维显示?】的修改原有代码实现订阅和发布的方式,本文创建了一个中间文件实现订阅和发布。

1、创建中间特殊文件(含订阅者和发布者)

  (1)在node.cpp同级目录下新建中间特殊文件middle_node.cpp;
  ROS开发之如何在同一个节点订阅、处理、发布消息?

  (2)输入以下代码。

/***
Copyright 2023 cacrle ( cacrle.blog.csdn.net).
***/#include "ros/ros.h"
#include <ros/package.h&gt;
#include "sensor_msgs/LaserScan.h"
#include "std_srvs/Empty.h"
#include "rplidar.h"
#include <pcl_ros/point_cloud.h&gt;
#include <pcl/point_types.h&gt;
#include <boost/foreach.hpp&gt;//declare point data formate
typedef pcl::PointCloud<pcl::PointXYZ&gt; PointCloud;
pcl::PointCloud<pcl::PointXYZ&gt; cloud_msg;//a changable height
float count_h = 0;
//Avoid redefine
#ifndef DEG2RAD
#define DEG2RAD(x) ((x)*M_PI/180.)
#endif//declare a publisher
ros::Publisher cloud_pub;//the callback method, will monitor the topic and receive message
void scanCallback(const sensor_msgs::LaserScan::ConstPtr&amp; scan_msg)
{int count = scan_msg-&gt;scan_time / scan_msg-&gt;time_increment;cloud_msg.header.frame_id = "laser";cloud_msg.height = 1;cloud_msg.width = count;cloud_msg.points.resize(cloud_msg.width * cloud_msg.height);for(int i = 0; i < count; i++){float degree = RAD2DEG(scan_msg-&gt;angle_min + scan_msg-&gt;angle_increment * i);cloud_msg.points[i].x = scan_msg-&gt;ranges[i] * cos(DEG2RAD(degree));cloud_msg.points[i].y = scan_msg-&gt;ranges[i] * sin(DEG2RAD(degree));cloud_msg.points[i].z = count_h;//print out data to screenROS_INFO("[%f, %f, %f]", cloud_msg.points[i].x ,cloud_msg.points[i].y, cloud_msg.points[i].z);}count_h += 0.05;if(count_h&gt;100){count_h = 0;}//converse ros time to pcl timepcl_conversions::toPCL(ros::Time::now(),cloud_msg.header.stamp);cloud_pub.publish(cloud_msg);
}int main(int argc, char **argv)
{//initial, "middle_node" is the name of cpp(i.e. midlle_node.cpp)ros::init(argc, argv, "middle_node");//declare a noderos::NodeHandle n;//declare a subscirberros::Subscriber sub = n.subscribe<sensor_msgs::LaserScan&gt;("scan", 1000, scanCallback);//give publisher a initial value, "point_cloud2" is topic, 1000 is frequency(unit is hz)cloud_pub = n.advertise<PointCloud&gt;("point_cloud2",1000);//program reach here and stop to next, this code may monitor the scanCallbackros::spin();return 0;
}

2、在CMakeLists.txt添加编译规则

  ROS开发之如何在同一个节点订阅、处理、发布消息?

cmake_minimum_required(VERSION 2.8.3)
project(rplidar_ros)set(RPLIDAR_SDK_PATH "./sdk/")FILE(GLOB RPLIDAR_SDK_SRC
"${RPLIDAR_SDK_PATH}/src/arch/linux/*.cpp"
"${RPLIDAR_SDK_PATH}/src/hal/*.cpp"
"${RPLIDAR_SDK_PATH}/src/*.cpp"
)
find_package(catkin REQUIRED COMPONENTS
roscpp
rosconsole
sensor_msgs
)include_directories(
${RPLIDAR_SDK_PATH}/include
${RPLIDAR_SDK_PATH}/src
${catkin_INCLUDE_DIRS}
/usr/include/pcl-1.7
/usr/include/eigen3
)catkin_package()
add_executable(rplidarNode src/node.cpp ${RPLIDAR_SDK_SRC})
target_link_libraries(rplidarNode ${catkin_LIBRARIES})add_executable(rplidarNodeClient src/client.cpp)
target_link_libraries(rplidarNodeClient ${catkin_LIBRARIES})add_executable(middle_node src/middle_node.cpp)
target_link_libraries(middle_node ${catkin_LIBRARIES})install(TARGETS rplidarNode rplidarNodeClient
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)install(DIRECTORY launch rviz sdk
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
USE_SOURCE_PERMISSIONS
)

3、在launch添加启动项

  ROS开发之如何在同一个节点订阅、处理、发布消息?

<launch&gt;
<node name="rplidarNode"          pkg="rplidar_ros"  type="rplidarNode" output="screen"&gt;
<param name="serial_port"         type="string" value="/dev/ttyUSB0"/&gt;
<param name="serial_baudrate"     type="int"    value="115200"/&gt;<!--A1/A2 --&gt;
<!--param name="serial_baudrate"     type="int"    value="256000"--&gt;<!--A3 --&gt;
<param name="frame_id"            type="string" value="laser"/&gt;
<param name="inverted"            type="bool"   value="false"/&gt;
<param name="angle_compensate"    type="bool"   value="true"/&gt;
</node&gt;<node name="middle_node"          pkg="rplidar_ros"  type="middle_node" output="screen"/&gt;
</launch&gt;

4、编译运行

cd ~/catkin_wscatkin_make
或
catkin_make_isolatedsource devel/setup.bash
或
source devel_isolated/setup.bashroslaunch rplidar_ros rplidar.launch

  ROS开发之如何在同一个节点订阅、处理、发布消息?

5、三维显示

  (1)RViz参数设置;
  ROS开发之如何在同一个节点订阅、处理、发布消息?

  (2)显示结果。
  ROS开发之如何在同一个节点订阅、处理、发布消息?

参考资料:
[1] cacrle. ROS如何进行开发?; 2023-04-10 [accessed 2023-04-13].
[2] cacrle. ROS开发之如何使用发布者、订阅者和话题消息?; 2023-04-12 [accessed 2023-04-13].
[3] cacrle. ROS开发之如何制作launch启动文件?; 2023-04-11 [accessed 2023-04-13].
[4] cacrle. ROS开发之如何使用RPLidar A1二维激光雷达?; 2023-04-11 [accessed 2023-04-13].
[5] cacrle. ROS开发之如何将树莓派采集的雷达、IMU数据在虚拟机rviz中显示?; 2023-04-12 [accessed 2023-04-13].
[6] cacrle. ROS开发之如何将RPLidar数据在RViz中三维显示?; 2023-04-12 [accessed 2023-04-13].
[7] cacrle. Windows与Linux 之间如何进行文件共享?; 2023-03-27 [accessed 2023-04-13].
[8] 十年前与现在. ros-同时订阅与发布; 2020-08-07 [accessed 2023-04-13].
[9] 白巧克力亦唯心. ROS 基础: 在同一个节点里订阅和发布消息; 2015-05-07 [accessed 2023-04-13].
[10] cyliujc. ros同时接收多话题并发布; 2017-12-04 [accessed 2023-04-13].
[11] 小萌是个球. ros::spin() 和 ros::spinOnce() 区别及详解 ; 2016-10-01 [accessed 2023-04-13].