ROS学习笔记
说明:<>中的内容表示必选项,[]中的内容表示可选项目
摘要:ROS的初级教程,包含创建ROS软件包,ROS节点的概念及rosnode应用。然后介绍ROS话题和服务的概念及创建过程。编写简单的发布者和订阅者以及简单的服务和客户端。还有一些小工具的使用,例如rqt_console, roslaunch, rosed, rosnode等
一、创建ROS软件包
来源:http://wiki.ros.org/cn/ROS/Tutorials/CreatingPackage
1. catkin工作空间中的软件包
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n
2. 创建catkin软件包
cd至src目录->创建
cd ${catkin_path}/src
catkin_create_pkg <package_name> [depend1] [depend2] [depend3] ...
Example01: 在src目录下创建beginner_tutorials软件包
cd ~/catkin_ws/src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
Example02: 在my_src目录下创建my_src_begin软件包
mkdir ~/catkin_ws/my_src
cd ~/catkin_ws/my_src
catkin_create_pkg my_src_begin roscpp rospy
3. 构建catkin工作区并生效配置文件
来源:http://wiki.ros.org/cn/ROS/Tutorials/BuildingPackages
构建->添加至ROS环境
cd ${catkin_path}
catkin_make [make_targets] [-DCMAKE_VARIABLES=...]
source ${catkin_path}/devel/setup.bash
Example01: 构建src下所有软件包
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash
Example02: 构建my_src下名为my_src_begin的软件包
cd ~/catkin_ws
catkin_make my_src_begin --source my_src
source ~/catkin_ws/devel/setup.bash
二、ROS节点
来源:http://wiki.ros.org/cn/ROS/Tutorials/UnderstandingNodes
1. 概念
计算图(Computation Graph)是一个由ROS进程组成的点对点网络,它们能够共同处理数据。ROS的基本计算图概念有节点(Nodes)、主节点(Master)、参数服务器(Parameter Server)、消息(Messages)、服务(Services)、话题(Topics)和袋(Bags),它们都以不同的方式向图(Graph)提供数据。
节点(Nodes):节点是一个可执行文件,它可以通过ROS来与其他节点进行通信。
消息(Messages):订阅或发布话题时所使用的ROS数据类型。
话题(Topics):节点可以将消息发布到话题,或通过订阅话题来接收消息。
主节点(Master):ROS的命名服务,例如帮助节点发现彼此。
rosout:在ROS中相当于stdout/stderr(标准输出/标准错误)。
roscore:主节点 + rosout + 参数服务器(会在以后介绍)。
节点实际上是ROS软件包中的一个可执行文件。ROS节点使用ROS客户端库与其他节点通信。节点可以发布或订阅话题,也可以提供或使用服务。节点是ROS中非常重要的一个概念,这里举一个通俗的例子:
例如,咱们有一个机器人,和一个遥控器,那么这个机器人和遥控器开始工作后,就是两个节点。遥控器起到了下达指 令的作用;机器人负责监听遥控器下达的指令,完成相应动作。从这里我们可以看出,节点是一个能执行特定工作任 务的工作单元,并且能够相互通信,从而实现一个机器人系统整体的功能。在这里我们把遥控器和机器人简单定义为两个节点,实际上在机器人中根据控制器、传感器、执行机构等不同组成模块,还可以将其进一步细分为更多的节点,这个是根据用户编写的程序来定义的。)
ROS客户端库可以让用不同编程语言编写的节点进行相互通信:1) rospy=python客户端库;2)roscpp=c++客户端库
roscore是运行所有ros程序前必须执行的命令
2. rosnode使用
rosnode list # 查看正在运行的ROS节点
rosnode info <node_name> # 查看ROS节点名为node_name的信息
rosrun <packpage_name> <node_name> # 运行ROS节点
Example01:
rosrun turtlesim turtlesim_node
rosrun <package_name> <node_name> __name:=new_name # 运行ROS节点,并重命名为new_name
Example01:
rosrun turtle_sim turtle_sim_node __name:=my_turtle
rosnode ping <node_name> # ping名为node_name的ROS节点来判断该节点是否正常
三、ROS话题
节点和节点之间通过话题相互通信。话题有以下几个要点:
a. 利用动态图rqt_graph显示系统中正在发生的事情
rosrun rqt_graph rqt_graph
b. 利用rostopic获取ROS话题的信息
rostopic -h # 显示该命令的帮助信息
rostopic echo <topic> # 显示在话题名为topic上发布的数据
rostopic list [args] # 显示当前已被订阅和发布的所有话题
c. 话题的通信通过节点之间发送ROS消息实现。发布者和订阅者的消息类型必须相同,故话题类型由消息类型决定
rostopic type <topic> # 查看所发布话题的消息类型
rosmsg show <msg_type> # 查看消息类型为msg_type的详细信息
d. 利用rostopic pub向指定话题发布消息
rostopic pub <topic> <msg_type> <args>
Example01: 向话题/turtle1/cmd_vel发送一次性消息,且消息类型为geometry_msgs/Twist,发布完成后自动退出。 --表示后续参数都不是选项
rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[1.8, 0.0, 0.0]' '[0.0, 0.0, 2.5]'
Example02: 向话题/turtle1/cmd_vel持续发送消息,发送频率为1hz,且消息类型为geometry_msgs/Twist
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[1.8, 0.0, 0.0]' '[0.0, 0.0, 2.5]'
e. 利用rostopic hz报告数据发布的频率
rostopic hz <topic> # 查看话题为topic的消息发送频率
Example01: 查看/teleop_turtle节点发布/turtle1/cmd_vel得有多快
rostopic hz /turtle1/cmd_vel
f. 利用rqd_plot在滚动时间图上显示发布到某个话题上的数据
rosrun rqt_plot rqt_plot
来源及示例:http://wiki.ros.org/cn/ROS/Tutorials/UnderstandingTopics
四、ROS服务及参数
参考:http://wiki.ros.org/cn/ROS/Tutorials/UnderstandingServicesParams
每次修改服务参数后都需要重新call一下才能生效
五、rqt_console和roslaunch
来源:http://wiki.ros.org/cn/ROS/Tutorials/UsingRqtconsoleRoslaunch
rosrun rqt_console rqt_console # 启动rqt_console
rosrun rqt_logger_level rqt_logger_level # 启动rqt_logger_level
rqt_console用于显示日志,rqt_logger_level选择日志级别
roslaunch需要编写launch文件,可以同时launch多个节点
roslaunch <package> <filename.launch>
Example01:
roslaunch beginner_tutorials turtlemimic.launch
六、rosed编辑ROS文件
参考:http://wiki.ros.org/cn/ROS/Tutorials/UsingRosEd
七、创建ROS消息和服务
参考:http://wiki.ros.org/cn/ROS/Tutorials/CreatingMsgAndSrv
八、编写简单的发布者和订阅者
1. 前置工作
roscd beginner_tutorials
mkdir scripts
cd scripts
2. 编写发布者节点talker.py
roscp rospy_tutorials talker.py scripts
chmod +x scripts/talker.py
talker.py具体内容如下:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
3. 编写订阅者节点
roscp rospy_tutorials listener.py scripts
chmod +x scripts/listener.py
listener.py具体内容如下:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
# In ROS, nodes are uniquely named. If two nodes with the same
# name are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
4. 添加至CMakeList.txt
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
5. 构建节点
cd ~/catkin_ws
catkin_make
6. 验证
a. 运行roscore
roscore
b. 运行发布者
cd ~/catkin_ws
source devel/setup.bash
rosrun beginner talker.py
c. 运行订阅者
rosrun beginner listener.py
九、编写简单的服务和客户端
1. 前置工作
source ~/catkin_ws/devel/setup.bash
roscd beginner
需要创建必须的服务节点
2. 编写服务节点
gedit scripts/add_two_ints_server.py
添加如下内容:
#!/usr/bin/env python
from __future__ import print_function
from beginner_tutorials.srv import AddTwoInts,AddTwoIntsResponse
import rospy
def handle_add_two_ints(req):
print("Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b)))
return AddTwoIntsResponse(req.a + req.b)
def add_two_ints_server():
rospy.init_node('add_two_ints_server')
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
print("Ready to add two ints.")
rospy.spin()
if __name__ == "__main__":
add_two_ints_server()
赋予文件执行权限
chmod +x scripts/add_two_ints_server.py
3. 编写客户端节点
gedit scripts/add_two_ints_client.py
添加如下内容:
#!/usr/bin/env python
from __future__ import print_function
import sys
import rospy
from beginner_tutorials.srv import *
def add_two_ints_client(x, y):
rospy.wait_for_service('add_two_ints')
try:
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
resp1 = add_two_ints(x, y)
return resp1.sum
except rospy.ServiceException as e:
print("Service call failed: %s"%e)
def usage():
return "%s [x y]"%sys.argv[0]
if __name__ == "__main__":
if len(sys.argv) == 3:
x = int(sys.argv[1])
y = int(sys.argv[2])
else:
print(usage())
sys.exit(1)
print("Requesting %s+%s"%(x, y))
print("%s + %s = %s"%(x, y, add_two_ints_client(x, y)))
赋予文件执行权限
chmod +x scripts/add_two_ints_client.py
4. 构建节点
cd ~/catkin_ws
catkin_make
5. 验证
a. 运行发布者
rosrun beginner add_two_ints_server```
b. 运行订阅者
```xml
rosrun beginner add_two_ints_client.py 1 3
十、roswtf
rosdep update出现错误解决方法
https://blog.csdn.net/super_sean/article/details/105433250