ROS基本编程--topic

本文最后更新于:2022年5月29日 上午

话题编程流程

  • 创建发布者
  • 创建订阅者
  • 添加编译选项
  • 运行可执行程序

1,创建程序包

1
2
cd catkin_ws/src/
catkin_create_pkg topic_demo roscpp std_msgs

2,修改package.xml作者邮箱

1
cd topic_demo;gedit package.xml

3,编译测试

1
2
cd ~/catkin_ws
catkin_make

4,定义新的消息

1
2
3
4
cd ~/catkin_ws/src/topic_demo
mkdir msg
cd msg
gedit gps.msg

输入以下代码并保存:

1
2
3
string state	#工作状态 
float32 x #x坐标
float32 y #y坐标

5,检查ROS是否能够识消息

使用rosmsg show命令:

1
rosmsg show topic_demo/gps

将会看到:

1
2
3
float32 x 
float32 y
string state

6,修改查看package.xml

查看package.xml, 确保它包含一下两条语句(接近末尾处),如果没有,添加进去:

1
2
<build_depend>message_generation</build_depend> 
<exec_depend>message_runtime</exec_depend>

7,修改CMakeLists.txt文件

1)在find_packag函数的COMPONENTS的列表里增加message_generation,就像这样:

1
2
3
4
5
find_package(catkin REQUIRED COMPONENTS 
roscpp
std_msgs
message_generation #需要添加的地方
)

2)设置运行依赖:
用于配置ROS和packge配置文件和Cmake文件

1
2
3
4
5
catkin_package(
...
CATKIN_DEPENDS message_runtime
...
)

3)用你的.msg文件替代Message*.msg

1
add_message_files(FILES gps.msg) #指定从哪个消息文件生成

4)取消generate_messages()的注释:

1
generate_messages(DEPENDENCIES std_msgs) #用于生成消息 #DEPENDENCIES后面指定生成msg需要依赖其他什么消息,由于gps.msg用到了flaot32这种ROS标准消息,因此需要再把std_msgs作为依赖

8,编译生成gps.msg对应的头文件

1
2
cd ~/catkin_ws
catkin_make

9,编写源代码

实现一个发布者

  • 初始化ROS节点;
  • 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;
  • 按照一定的频率循环发布消息。

1)创建消息发布节点

1
2
roscd topic_demo/src/
gedit talker.cpp

输入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <ros/ros.h>			
#include <topic_demo/gps.h> //自定义msg产生的头文件

int main(int argc, char **argv)
{
ros::init(argc, argv,"talker"); //用于解析ROS参数,第三个参数为本节点名
ros::NodeHandle n; //实例化句柄,初始化node
topic_demo::gps msg; //自定义gps消息并初始化
msg.x = 1.0;
msg.y = 1.0;
msg.state = "working";
ros::Publisher pub = n.advertise<topic_demo::gps>("gps_info",1); //创建publisher,往"gps_info"话题上发布消息
ros::Rate loop_rate(1.0); //定义发布的频率,1HZ
while(ros::ok()) //循环发布msg
{
msg.x = 1.03 * msg.x;
msg.y = 1.01 * msg.y;
ROS_INFO("Talker: GPS: x = %f, y = %f",msg.x,msg.y);
pub.publish(msg); //发布m消息
loop_rate.sleep(); //根据前面的定义的loop_rate,设置1s的暂停
}
return 0;
}

实现一个订阅者

  • 初始化ROS节点;
  • 订阅需要的话题;
  • 循环等待话题消息,接收到消息后回调函数;
  • 在回调函数中完成消息处理。

2)创建消息接收节点

1
gedit listener.cpp

输入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <ros/ros.h>
#include <topic_demo/gps.h>
#include <std_msgs/Float32.h>

void gpsCallback(const topic_demo::gps::ConstPtr &msg)
{
std_msgs::Float32 distance; //计算离原点(0,0)的距离
distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2));
ROS_INFO("Listener: Distance to origin = %f, state: %s",distance.data,msg->state.c_str()); //输出
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback); //设置回调函数gpsCallback

ros::spin(); //ros::spin()用于调用所有可触发的回调函数,将进入循环,不会返回,类似于在循环里反复调用spinOnce()
//而ros::spinOnce()只会去触发一次
return 0;
}

10,修改CMakeLists.txt文件

在 CMakeLists.txt 添加以下内容,生成可执行文件。

1
2
3
4
5
6
7
8
9
add_executable(talker	src/talker.cpp)	#生成可执行文件talker
add_dependencies(talker topic_demo_generate_messages_cpp)
#表明在编译talker前,必须先生编译完成自定义消息
#必须添加add_dependencies,否则找不到自定义的msg产生的头文件
#表明在编译talker前,必须先生编译完成自定义消息
target_link_libraries(talker ${catkin_LIBRARIES}) #链接
add_executable(listener src/listener.cpp) #声称可执行文件listener
add_dependencies(listener topic_demo_generate_messages_cpp)
target_link_libraries(listener ${catkin_LIBRARIES})#链接

11,编译

1
2
cd ~/catkin_ws
catkin_make

12,运行

1、启动master节点

打开新终端输入命令:

1
roscore

2、启动talker节点

1
rosrun topic_demo talker

3、启动talker节点

1
rosrun topic_demo listener

15ZhuT.png


ROS基本编程--topic
https://kevinloongc.github.io/posts/59037.html
作者
Kevin Loongc
发布于
2019年4月22日
许可协议