文章只是个人学习过程中学习笔记,主要参考ROS教程1 2 3。
1、概述
msg
(消息)文件就是文本文件,用于描述ROS消息的字段。它们用于为不同编程语言编写的消息生成源代码。
msg
文件存放在软件包的msg目录下。
2、msg结构和类型
msg4文件就是简单的文本文件,每行都有一个字段类型和字段名称。它的结构为:
fieldtype
+ fieldname
2.1 类型
可以使用的类型为:
- int8, int16, int32, int64 (以及 uint*)
- float32, float64
- string
- time, duration
- 其他msg文件
- variable-length array[] 和 fixed-length array[C]
2.2 举例
# 特殊的Header类型,它含有时间戳和ROS中广泛使用的坐标帧信息
# 在msg文件的第一行经常可以看到Header header。
std_msgs/Header header
uint8 is_true
uint32 height
uint32 width
string child_frame_id
time stamp
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
uint8[] data
3、msg命令rosmsg
rosmsg
显示有关ROS消息类型的信息。
命令 | 功能 |
---|---|
rosmsg show | 显示消息的描述(详细信息) |
rosmsg info | rosmsg show 的别名,功能一样 |
rosmsg list | 列出所有消息 |
rosmsg md5 | 显示md5加密的消息 |
rosmsg package | 列出某个软件包(package)的消息 |
rosmsg packages | 列出包含消息的软件包(packages) |
4、msg的用法
4.1 创建msg
还是在原来创建的软件包 beginner_tutorials
中定义一个新的消息。
# 切换到软件包的目录路径
roscd beginner_tutorials
# 创建msg文件夹目录
mkdir msg
# 创建名为Num.msg的文件,并添加一个消息字段
echo "int64 num" > msg/Num.msg
4.2 配置CMakeLists.txt
1. 为已经存在里面的find_package调用添加message_generation
依赖项(),这样就能生成消息了。(添加 message_generation
依赖项,必须有 std_msgs
。)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
2. 添加自定义的消息文件。将你msg
文件夹中自定义的*.msg
文件添加在这里。
add_message_files(
FILES
Num.msg
)
3. 用于生成所有定义的message文件,需要添加本文件需要依赖的packages。其实就是告诉编译器,编译 *.msg
文件时,需要依赖的库或package。
generate_messages(
DEPENDENCIES
std_msgs
)
4. 导出消息的运行时依赖关系。
catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)
4.3 配置package.xml
添加编译依赖与执行依赖。
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
Node
:在构建时,其实只需要message_generation
,而在运行时,我们只需要message_runtime
。
4.4 编译package
已经创建了一些新消息,所以需要重新make一下软件包:
cd
cd catkin_ws
catkin_make
msg目录中的任何.msg文件都将生成所有支持语言的代码。
- C++消息的头文件将生成在
~/catkin_ws/devel/include/beginner_tutorials/
- python脚本将创建在
~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg
5、msg命令实操
5.1 rosmsg list
rosmsg list
列出ROS中的所有消息(msg)。
5.2 rosmsg packages
rosmsg packages [options]
列出包含消息的软件包。
# 列出包含消息的软件包,每行显示一个软件包名
rosmsg packages
# 在一行中列出包含消息的软件包
rosmsg packages -s
5.3 rosmsg package
rosmsg package [package-name]
列出某个软件包(package)的消息。
5.4 rosmsg show / rosmsg info
rosmsg show [message type]
显示消息的详细信息。
5.5 rosmsg md5
rosmsg md5[message type]
显示md5加密的消息。如果编译的版本不匹配,这也会发出警告。
Node
:md5 命令仅供专家用户使用。(??)
6、实操编程 – 话题通信发送自定义消息
功能:基于话题通信,发布者以一定频率发布自定义消息并打印输出消息,订阅者订阅自定义消息并打印输出消息。
实现:
1. 创建发布者(talker
)节点,该节点不断广播自定义消息。
2. 创建订阅者(listener
)节点,该节点持续接收自定义消息。
3. 创建自定义消息(Num.msg
),(见4.1小节 创建msg
)
4. 发布订阅话题chatter
6.1 编写程序(C++)
在beginner_tutorials
软件包的src目录下创建发布者和订阅者源文件:
roscd beginner_tutorials
cd src
touch talker.cpp listener.cpp
6.1.1 发布者程序(talker.cpp)
#include "ros/ros.h"
#include "beginner_tutorials/Num.h" // 在 /devel/include 目录下
int main(int argc, char **argv)
{
/* 防止中文乱码 */
setlocale(LC_ALL,"");
/* 初始化ROS节点 */
ros::init(argc, argv, "talker");
/* 为这个进程节点创建句柄 */
ros::NodeHandle nh;
/* 创建发布者对象 */
ros::Publisher pub = nh.advertise<beginner_tutorials::Num>("chatter", 1000);
/* 设定循环发布的频率为1Hz */
ros::Rate loop_rate(1);
/* 要发布的消息 */
beginner_tutorials::Num msg;
msg.num = 0;
while(ros::ok())
{
ROS_INFO("当前num值为: %d",msg.num);
/* 发布消息 */
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.num += 1;
}
return 0;
}
对上边的内容进行一下总结:
- 初始化ROS系统
- 向主节点宣告我们将要在
chatter
话题上发布beginner_tutorials/Num
类型的消息- 以每秒1次的速率向
chatter
话题循环发布消息
6.1.2 订阅者程序(listener.cpp)
#include "ros/ros.h"
#include "beginner_tutorials/Num.h" // 在 /devel/include 目录下
/* 回调函数,当有新消息到达chatter话题时就会调用 */
void chatterCallback(const beginner_tutorials::Num::ConstPtr& msg)
{
ROS_INFO("已收到的Num的值: %d",msg->num);
}
int main(int argc, char **argv)
{
/* 防止中文乱码 */
setlocale(LC_ALL,"");
/* 初始化ROS节点 */
ros::init(argc, argv, "listener");
/* 为这个进程节点创建句柄 */
ros::NodeHandle nh;
/* 创建订阅者对象
* 通过节点管理器订阅chatter话题。收到消息,调用回调函数chatterCallback。
* 第2个参数是队列大小,>1000时,丢弃旧消息。
*/
ros::Subscriber sub = nh.subscribe("chatter",1000, chatterCallback);
/* 启动自循环 回调函数处理, 不占用太多CPU */
ros::spin();
return 0;
}
同样地,我们来总结一下:
- 初始化ROS系统
- 订阅
chatter
话题- 开始spin自循环,等待消息的到达
- 当消息到达后,调用
chatterCallback()
函数
6.1.3 配置CMakeLists.txt
只需将这几行添加到CMakeLists.txt文件的底部:
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener ${PROJECT_NAME}_generate_messages_cpp)
6.1.4 编译、运行
编译后,在终端中执行过程如下所示。
6.2 编写程序(python)
在beginner_tutorials
软件包的scripts
目录下创建发布者和订阅者源文件:
roscd beginner_tutorials
cd scripts
touch talker.py listener.py
chmod +x talker.py listener.py
6.2.1 发布者程序(talker.py)
#!/usr/bin/env python
# encoding: utf-8
import rospy
from beginner_tutorials.msg import Num
def talker():
# 初始化ROS节点
rospy.init_node("talker",anonymous=True)
# 创建发布者对象
pub = rospy.Publisher('chatter', Num, queue_size=1000)
# 创建一个Rate对象rate,1Hz
rate = rospy.Rate(1)
# 要发布的消息
msg = Num()
msg.num = 0
# 循环
while not rospy.is_shutdown():
rospy.loginfo("当前num值为: %d",msg.num)
pub.publish(msg)
rate.sleep()
msg.num += 1
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
6.2.2 订阅者程序(listener.py)
#!/usr/bin/env python
# encoding: utf-8
import rospy
from beginner_tutorials.msg import Num
def callback(msg):
rospy.loginfo("已收到的Num的值: %d",msg.num)
def listener():
# 初始化ROS节点
rospy.init_node("listener",anonymous=True)
# 创建发布者对象
pub = rospy.Subscriber('chatter', Num, callback, queue_size=1000)
rospy.spin()
if __name__ == '__main__':
listener()
6.2.3 配置CMakeLists.txt
# 安装python可执行脚本
catkin_install_python(PROGRAMS
scripts/turtle_publisher.py
scripts/talker.py
scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
6.1.4 编译、运行
编译后,在终端中执行过程如下所示。
ROS.otg. ROS教程[EB/OL]. 2020-12-22[2022-7-5].
http://wiki.ros.org/cn/ROS/Tutorials. ↩︎.ROS.org. 编写简单的发布者和订阅者(C++)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29. ↩︎
.ROS.org. 编写简单的发布者和订阅者(Python)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29. ↩︎
ROS.org. msg[EB/OL]. https://wiki.ros.org/msg[2022-07-30]. https://wiki.ros.org/msg. ↩︎