ROS(Robot Operating System)机器人操作系统实际上是提供了多节点协同机制,使用了话题、服务、参数服务器、action等通信机制,同时ROS还提供了Gazebo、rviz、rqt、rosbag等工具,这些工具的本质也是对通信消息的收发。
ROS本身提供了点对点网络,共同处理数据,它的基本概念包括节点、主节点、参数服务器、消息、服务、话题、包等等。
分别使用
rospack
-获取软件包有关信息
:查看软件包依赖,
roscd
-切换到软件包目录
rosls
-查看软件包包含文件
rosnode
-查看ros节点相关信息
:查看节点列表,查看节点消息属性
rosrun
-运行软件包-某一节点功能
:rqt-graph
rostopic
-获取话题相关信息
rosservice
-获取服务相关信息
rosparam
-获取参数相关信息
roslaunch
-启动launch文件
rosmsg
-查看消息有关信息
可以使用Tab
补全代码
整个ROS程序的完整结构是
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
- 初始化工作空间
mkdir -p my_workspace/src
cd my_workspace/src
- 创建软件包
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
- 创建catkin工作区,生效配置文件
使用catkin_make
,即在CMAKE标准工作流中依次调用了cmake和make。
cd ..
catkin_make
catkin_make install
# 等价于在CMAKE工作空间下执行:
# mkdir build | cd build | cmake .. | make | make install
- 运行软件包和查看系统结构
运行键盘控制小乌龟运动的示例功能,在多个终端窗口分辨运行下面指令
roscore
rosrun turtlesim turtlesim_node __name:=my_turtle
rosrun turtlesim turtle_teleop_key
检查通信的层次方向
rosrun rqt_graph rqt_graph
- rostopic 指令详述
(1)echo
-接收话题消息数据
-rostopic echo <topic_name>
(2)pub
-发布话题消息数据
-rostopic pub <topic_name> <msgs_type> [args]
# 发布一次小乌龟速度话题消息数据
rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
# 以1Hz的频率持续发布小乌龟速度话题数据
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'
(3)hz
-查看数据发布速率
-``
- rosservice 指令详述
(1)rosservice list 获取服务列表
(2)rosservice call
- rosparam 指令详述
#(1)rosparam list 获取参数列表
#(2)rosparam get [param_name] 获取参数值
#(3)rosparam set [param_name] [args] 设置参数值
#(4)rosparam load [yaml_name] ([namespace]) 从文件中加载参数(载入新的命名空间)
#(5)rosparam sump [yaml_name] ([namespace]) 向文件中转储参数(载入新的命名空间)
#(6)rosparam delete [param_name] 删除参数
- rqt 指令详述
(1)查看节点传递消息层次:rosrun rqt_graph rqt_graph
(2)查看数据图:rosrun rqt_plot rqt_plot
(3)查看日志框架:rosrun rqt_console rqt_console
(4)查看信息的详细级别:rosrun rqt_logger_level rqt_logger_level
- roslaunch
在软件包(如beginner_tutorials)文件夹内创建launch文件家,用于保存launch文件。
<launch>
<!--
创建两个分组,命名空间分别为turtlesim1,turtlesim2
它们都包含名为sim的turtlesim节点,
-->
<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>
<!--
启动模仿节点,模仿的输入和输出分别为turtlesim1和turtlesim2
-->
<node pkg="turtlesim" name="mimic" type="mimic">
<remap from="input" to="turtlesim1/turtle1"/>
<remap from="output" to="turtlesim2/turtle1"/>
</node>
</launch>
在终端窗口运行launch文件和发布话题消息
roslaunch beginner_tutorials turtlemimic.launch
rostopic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'
其中消息传递的层次是
13. rosed 操作详述
rosed
是rosbash
套件的一部分,可以用来编辑包中文件
设置默认编辑器
详细操作见:http://wiki.ros.org/cn/ROS/Tutorials/UsingRosEd
10.创建ROS消息和服务
(1)基本介绍
消息(.msg)和服务(.srv)都是文本文件,一般分别放置在软件功能包中的msg
和srv
文件夹中(与launch
平级),用于为不同语言编写的消息生成源代码,msg只有一个部分,而服务分为请求和响应。
(2)类型格式
可用类型:
- int8, int16, int32, int64 (以及 uint*)
- float32, float64
- string
- time, duration
- 其他msg文件
- variable-length array[] 和 fixed-length array[C]
.srv
文件用一条---
将请求和响应两部分上下分开,如:
int64 A
int64 B
---
int64 Sum
(3)创建消息或服务
为保证能够转换成为C++、python或者其他语言的源代码(即若需要自己构建消息类型),需要在package.xml
、CMakeLists.txt
中添加相关代码:
对于消息
package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
CMakeLists.txt
find_package
中添加message_generation
catkin_package
取消注释,并在CATKIN_DEPENDS后面添加message_runtime
add_message_files
取消注释,并添加message_name.msg
generate_messages
取消注释
对于服务
package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
CMakeLists.txt
find_package
中添加message_generation
catkin_package
取消注释,并在CATKIN_DEPENDS后面添加message_runtime
add_service_files
取消注释,并添加service_name.srv
generate_messages
取消注释
添加完成后,退回工作空间,使用catkin_make
重新编译ROS包,编译完成后,自行创建的消息类型就被加载到rosmaster中了,可以通过rosmsg show <message_name>
或rossrv show <service_name>
查看消息详细信息。
11.编写简单的发布者和订阅者
C++
(1).cpp文件添加
在前面创建的pkg/src
中添加talker.cpp
文件,在其中初始化名为talker_init
的节点。(talker.cpp和listenter.cpp的代码见节尾)
(2)CMakeLists.txt添加
在CMakeLists.txt
的末尾添加
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)
代码解释
add_executable(<exable file_name> <relative file_path>)
target_link_libraries(<exable file_name> ${catkin_LIBRARIES})
add_dependencies(<exable file_name> ${${PROJECT_NAME}_EXPORTED_TARGETS})
(3)编译和运行
在workspace
执行catkin_make
编译指令,可以调用rosrun <pkg_name> <exable file_name>
,即rosrun beginner_tutorials talker
。
/*talker.cpp*/
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
// 初始化ROS,指定节点名,此处的节点名必须是唯一的
ros::init(argc, argv, "talker_initname");
// 创建进程句柄
ros::NodeHandle n;
// 创建话题发布者,定义其名字和消息类型,以及最多缓存的消息条数
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// 指定循环频率
ros::Rate loop_rate(10);
int count = 0;
/* 若没有出现:
(1)Ctrl+C;
(2)被同名节点提出网络;
(3)ros::shutdown()被程序另一部分调用;
(4)ros::NodeHandles都被销毁。
则ros::ok()返回true*/
while(ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
// 发布消息
chatter_pub.publish(msg);
// 与回调函数相关
ros::spinOnce();
// 睡眠指定时间
loop_rate.sleep();
++count;
}
return 0;
}
/*listener.cpp*/
#include "ros/ros.h"
#include "std_msgs/String.h"
// 定义接收到消息时的回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener_initname");
ros::NodeHandle n;
// 创建订阅者,指定可以累积接收的消息数,指定回调函数
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
// 自循环函数,一旦ros::ok()返回false,将自动退出
ros::spin();
return 0;
}
python
(1)添加.py文件
一般习惯在前面创建的pkg
中创建scripts
文件夹,在其中添加talker.py
文件,在其中初始化名为talker_init_py
的节点。右击.py
文件的属性,将其设置为可以作为程序执行
。(talker.py和listenter.py的代码见节尾)
(2)在CMakeList.txt中添加(可以不做这一步)
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
(3)运行
若进行了第二步,需切换到工作空间目录执行catkin_make
。
使用rosrun <pkg_name> <filename.py>
运行。
"""talker.py"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# license removed for brevity
import rospy
from std_msgs.msg import String
# 创建发布者函数
def talker():
# 创建话题发布者对象,指定其名字,消息类型,最大累积队列长度
pub = rospy.Publisher('chatter', String, queue_size=10)
# 初始化节点,指定节点名,anonymous = True会让名称末尾添加随机数,来确保节点具有唯一的名称。
rospy.init_node('talker_init_py', anonymous=True)
# 设置发布频率
rate = rospy.Rate(10)
# 如果节点没有被关闭
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
# ros消息框
rospy.loginfo(hello_str)
# 发布消息
pub.publish(hello_str)
# 睡眠指定时间
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.POSInterruptException:
pass
"""listener.py"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from std_msgs.msg import String
# 创建回调函数
def callback(data):
# 在ros窗口显示消息
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
# 初始化节点
rospy.init_node('listener_init_py', anonymous=True)
# 指定订阅者对象
rospy.Subscriber("chatter", String, callback)
# 自循环函数
rospy.spin()
if __name__ == '__main__':
listener()
进阶库学习
navigate 导航模块
首先跑通一个demo对navigate模块建立整体的认识,下载中国大学慕课《机器人操作系统入门》的代码(视频和代码链接见文末),根据其中的md文件配置ros工作空间和编译,
slam例子
分别输入指令:
roscore
# roslaunch slam_sim_demo <launchfilename>
roslaunch slam_sim_demo gmapping_demo.launch
roslaunch slam_sim_demo view_slam.launch
在rviz
环境中使用2D Nav Goal
指定目标点
跑通的gmapping_demo层次结构如图:
navigation本身是一个metapackage,是一个功能包的集合。
是一个二维的导航功能包。
灰色(可替代)
蓝色(必须提供)
move_base的功能包括全局规划、局部规划、处理异常行为,可以把它看做有三个接口,如下图所示,针对每个接口,都可以指定相应的程序,而这三个接口插件都集成了nav_core
这个接口类。
cost_map是move_base的一个插件,与map不同的是,cost_map用于路径规划,是有多个层叠加的结果,如static layer(静态)、obstacle layer(动态和三维)、inflation layer(膨胀信息)。
map_server提供一直地图的信息,发布的topic为占用栅格数值和地图信息,提供静态地图服务,提供frame的参数服务器。
amcl为蒙特卡洛自适应定位方法,输入的参数有/tf、/scan和/map,输出的参数为/tf、/amcl_pose和/map,相较于传统的纯里程计(odom)定位,会将里程计的漂移补到odom计和map之间。
navigation例子
roscore
ROS资料:
- ROS wiki cn:http://wiki.ros.org/cn/ROS/Tutorials
- ROS导航官方库:
- 【奥特学院】ROS机器人入门课程《ROS理论与实践》零基础教程:https://www.bilibili.com/video/BV1Ci4y1L7ZZ,课程文档:http://www.autolabor.com.cn/book/ROSTutorials/
- 中国大学慕课,课程代码:https://github.com/GetOverMassif/ROS-Academy-for-Beginners,课程文档:https://sychaichangkun.gitbooks.io/ros-tutorial-icourse163/content/