本人ROS小白,利用寒假时间学习ROS,在此以笔记的方式记录自己每天的学习过程。争取写满20篇(2/20)。
环境:Ubuntu20.04、ROS1:noetic
环境配置:严格按照下方学习链接的教程配置,基本一次成功。
学习链接:【Autolabor初级教程】ROS机器人入门
对应链接文档:ROS机器人入门课程《ROS理论与实践》
笔记绝大部分代码使用Python语言编写。
本期关键词:理论模型,发布,订阅,自定义msg
这里先简要概述话题通信自定义msg的内容,接下来的“发布者实现“和“订阅者实现”会结合代码来演示如何使用自定义消息类型msg。
std_msgs
依赖包里,例如String
、Int32
、Char
等(该依赖包里的数据类型首字母就是大写的)。std_msgs
包里的数据类型是不能满足我们的要求的,ROS允许用户自定义数据类型,来满足用户特定场景下的需求。msg
目录,添加Person.msg
文件,名字是自定义的,你也可以叫Man.msg
。(msg文件名称的首字母最好大写。)string
、int16
、float64
这些。注意:不要直接int
、float
、char
这几个C语言的数据类型,msg文件和这些还是有些区别的,下面列举一些msg文件允许的字段类型:
package.xml文件修改:
在原来文件的基础上添加两行,即
message_generation
和message_runtime
整体如下:roscpp等包是原来添加依赖库时自动创建的
catkin
roscpp
rospy
std_msgs
message_generation
roscpp
rospy
std_msgs
roscpp
rospy
std_msgs
message_runtime
CMakeLists.txt文件修改
第一部分:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
第二部分:
add_message_files(
FILES
Person.msg
)
第三部分:这个不用添加东西,直接取消注释就行
enerate_messages(
DEPENDENCIES
std_msgs
)
第四部分:只用取消一行的注释
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES helloworld
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
catkin_make
指令编译一下,没有报错就问题不大。devel/lib/python3/msg/
目录下能找到_Person.py
文件,则表示msg文件配置成功。(记住这个路径的文件,待会会用到。)_Person.py
所在目录下打开终端,执行pwd
指令查看当前目录路径,选中/home/用户名/工作空间/devel/lib/python3/dist-packages
部分,添加到settings.json
文件中,如下所示。这一步的目的是方便接下来的代码编写(会自动补齐内容),不添加也不会影响编译运行。{
"python.autoComplete.extraPaths": [
"/opt/ros/noetic/lib/python3/dist-packages",
"/home/用户名/工作空间/devel/lib/python3/dist-packages"
],
"python.analysis.extraPaths": [
"/opt/ros/noetic/lib/python3/dist-packages",
"/home/用户名/工作空间/devel/lib/python3/dist-packages"
]
}
我们在执行代码的过程中,会经常用到
source ./devel/setup.bash
指令,虽然指令并不复杂,但是每新开一次终端都得输入一次,效率还是蛮低的。除此之外,使用Python编写代码,我们需要对新建的Python文件进行权限修改操作:chmod +x *.py
,这条指令也不复杂,但是输入多了效率也挺低的。
为了解决以上问题,我修改主目录下的.bashrc文件,在其末尾添加以下内容:
alias g-path='source ./devel/setup.bash'
alias get-x='chmod +x *.py'
(添加完之后要执行source .bashrc
指令让其生效)
添加之后,以后要输入source ./devel/setup.bash
指令就可以用g-path
代替,同理,chmod +x *.py
可以用get-x
代替。
demo_pub.py
。#! /usr/bin/env python
import rospy
from std_msgs.msg import String
if __name__ == "__main__":
rospy.init_node("talker_pub")
pub = rospy.Publisher("chat",String,queue_size=10)
msg=String()
cont="hello! How are you? "
count=0
rate=rospy.Rate(1)
rospy.sleep(3.0)
while not rospy.is_shutdown():
msg.data=cont+str(count)
pub.publish(msg)
rate.sleep()
rospy.loginfo("output data is: %s",msg.data)
count+=1
catkin_install_python
内容下:(由于CMakeLists.txt文件的修改方法比较简单,之后的文章可能不会提及。)catkin_install_python(PROGRAMS
scripts/hello_p.py # 这是之前添加的
scripts/demo_pub.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Person.msg
文件,配置方法参考上文。string name
int16 age
float64 height
#! /usr/bin/env python
import rospy
from helloworld.msg import Person
if __name__ == "__main__":
rospy.init_node("pub_msg")
pub = rospy.Publisher("msg_test",Person,queue_size=10)
p=Person()
p.name="Zhang San"
p.age=18
p.height=1.78
rate=rospy.Rate(1)
while not rospy.is_shutdown():
pub.publish(p)
rate.sleep()
rospy.loginfo("name is: %s, age is: %d, height is: %f", p.name,p.age,p.height)
代码如下:
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
def doMsg(msg):
rospy.loginfo("listener get: %s",msg.data)
if __name__=="__main__":
rospy.init_node("listener_sub")
sub = rospy.Subscriber("chat",String,doMsg,queue_size=10)
rospy.spin()
代码如下:(msg文件已经创建编译,直接用就行)
#! /usr/bin/env python
import rospy
from helloworld.msg import Person
def doMsg(p):
rospy.loginfo("I get: name is: %s, age is: %d, height is: %2f",p.name,p.age,p.height)
if __name__=="__main__":
rospy.init_node("sub_msg")
sub = rospy.Subscriber("msg_test",Person,doMsg,queue_size=10)
rospy.spin()
rospy.Subscriber
或rospy.Publisher
的第一个参数就是话题名。rospy.init_node()
指定的就是发布方或订阅方。rospy.spin()
的作用:让ROS节点保持运行状态,以便能够处理消息和回调。如果不调用 rospy.spin()
,你的程序可能会在执行完所有初始化代码后立即退出,这样回调函数就无法被触发。