在制作手势识别小车的最后,我计划使用Ros将各部分串连,实现一个完整的控制系统,这里记录一下博主ros的学习路径,一切以实用为主。
——————————————————
推荐资料:
1.在最开始,推荐观看古月居的视频(直接B站搜索),进行ROS环境的搭建,以及ROS相关概念的培养,一直到实现控制小乌龟以及查看参数就可以停止了,订阅器和发布器的相关概念也可以瞅瞅,视频使用的是C++作为例程,而博主打算使用的是Python,所以到这里就可以开始看接下来的网站。
2.接下来的学习都是按照此网站步骤进行。网站戳这里
3.ROS相关函数建议在官网直接看,写的很详细。戳这里
———————————————————
博主使用Ubuntu18.04+Pycharm作为开发环境
————————————————————
网站写的很详细直接看
还有构建catkin包
Catkin软件包必须包含:
1.符合catkin规范的packa.xml文件
2.这个包必须有一个catkin版本的CMakeLists.txt文件
3.每个包必须有自己的目录,即同一个目录下不能有嵌套的或者多个软件包存在
在构建Catkin包的过程中,在
$ rospack depends1 beginner_tutorials
这句时,报错
Error: package 'beginner_tutorials' depends on non-existent package 'rospyt' and rosdep claims
that it is not a system dependency. Check the ROS_PACKAGE_PATH or try calling 'rosdep update'
按照提示执行
rosdep update
因为网站被墙一直失败,搜了很多办法,最后成功的是按照这些博客解决的
戳这里
Time out解决方案
在向package.xml添加完依赖包后遇到报错
Error(s) in /home/leonsun/dev/catkin_ws/src/chapter2_tutorials/package.xml:
- The manifest (with format version 2) must not contain the following tags: run_depend
发现indigo版本之后的都需要把
<run_depend>message_runtimerun_depend>
改为
<exec_depend>message_runtimeexec_depend>
在执行catkin_make时报错
CMake Error at /opt/ros/melodic/share/catkin/cmake/catkinConfig.cmake:83 (find_package):
Could not find a package configuration file provided by
"socketcan_interface" with any of the following names:
socketcan_interfaceConfig.cmake
socketcan_interface-config.cmake
Add the installation prefix of "socketcan_interface" to CMAKE_PREFIX_PATH
or set "socketcan_interface_DIR" to a directory containing one of the above
files. If "socketcan_interface" provides a separate development package or
SDK, be sure it has been installed.
Call Stack (most recent call first):
robotiq/robotiq_3f_gripper_control/CMakeLists.txt:4 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/li/catkin_ws/build/CMakeFiles/CMakeOutput.log".
See also "/home/li/catkin_ws/build/CMakeFiles/CMakeError.log".
Invoking "cmake" failed
这是缺少依赖包,按照此教程解决
戳这
在解决完这些问题后,终于完成了工作空间的创建,接下来进行第二步。
作为ROS的通信方式之一,话题是一种异步通信机制,使用发布/订阅模型,数据由发布者传输到订阅者,同一个话题的订阅者和发布者可以不唯一,这是一种单向的传输机制,即发布者以广播的形式不断发布信息,一个或多个订阅者可以订阅这个发布者,就可以获得发布者传递的信息。
接下来是节点的创建,分别作为发布和订阅用。
1.在beginner_tutorials,新建msg消息目录,新建Num.msg文件
$ roscd beginner_tutorials
$ mkdir msg
$ cd msg
$ touch Num.msg
$ rosed beginner_tutorials Num.msg
msg(消息):msg文件就是文本文件,用于描述ROS消息的字段。它们用于为不同编程语言编写的消息生成源代码
msg文件 存放在软件包的msg目录下
msg文件 就是简单的文本文件,每行都有一个字段类型和字段名称。可以使用的类型为:
int8, int16, int32, int64 (以及 uint*)
float32, float64
string
time, duration
其他msg文件
variable-length array[] 和 fixed-length array[C]
ROS中还有一个特殊的数据类型:Header,它含有时间戳和ROS中广泛使用的坐标帧信息。在msg文件的第一行经常可以看到Header header。
2. 编写Num.msg文件,输入代码:
int64 num
3. 开文件rosed beginner_tutorials package.xml,增加依赖:
<build_depend>message_generationbuild_depend>
<exec_depend>message_runtimeexec_depend>
构建时,其实只需要message_generation,而在运行时,我们只需要message_runtime。
4. 打开文件rosed beginner_tutorials CMakeLists.txt,增加依赖
直接把cmakelists文件里面这些函数的注释去掉,末尾加新的依赖
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES beginner_tutorials
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
5.编译代码:
$ cd ~/catkin_ws
$ catkin_make
6.检查服务:
rosmsg show beginner_tutorials/Num
rosmsg show [message type]
beginner_tutorials – 定义消息的软件包
Num – 消息的名称
输出
int64 num
7.编写发布器:
进入之前建立的包beginner_tutorials
$ roscd beginner_tutorials
建立Python脚本目录
$ mkdir scripts
$ cd scripts
新建talker.py文件,设置权限为可执行,并输入代码
$ touch talker.py #生成文件
$ chmod +x talker.py #设置可执行
$ rosed beginner_tutorials talker.py #自己输入代码
#!/usr/bin/env python
#每个Python ROS节点的最开头都有这个声明。第一行确保脚本作为Python脚本执行。
import rospy
from std_msgs.msg import String
#如果要编写ROS节点,则需要导入rospy。std_msgs.msg的导入则是为了使我们能用std_msgs/String消息类型(即一个简单的字符串容器)来发布。
def talker():
#pub = rospy.Publisher("chatter", String, queue_size=10)声明该节点正在使用String消息类型发布到chatter话题。
#这里的String实际上是std_msgs.msg.String类。queue_size参数是在ROS Hydro及更新版本中新增的,用于在订阅者接收消息的速度不够快的情况下,限制排队的消息数量。
#对于ROS Groovy及早期版本来说,只需省略即可。
pub = rospy.Publisher('chatter', String, queue_size=10)
#将该节点的名字告诉rospy,名称必须是基本名称,不能包含任何斜杠/
#anonymous = True会让名称末尾添加随机数,来确保节点具有唯一的名称
rospy.init_node('talker', anonymous=True)
#此行创建一个Rate对象rate。借助其方法sleep(),来以你想要的速率循环。
#它的参数是10,即表示希望它每秒循环10次
rate = rospy.Rate(10) # 10hz
#检查rospy.is_shutdown()标志,然后执行代码逻辑
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
#打印消息到屏幕上;把消息写入节点的日志文件中;写入rosout。
#rosout是一个方便的调试工具:您可以使用rqt_console来拉取消息,而不必在控制台窗口找你节点的输出
rospy.loginfo(hello_str)
#将一个字符串发布到chatter话题
pub.publish(hello_str)
rate.sleep()
#除了标准的Python __main__检查,它还会捕获一个rospy.ROSInterruptException异常,
#当按下Ctrl+C或节点因其他原因关闭时,这一异常就会被rospy.sleep()和rospy.Rate.sleep()抛出。
#引发此异常的原因是你意外地在sleep()之后继续执行代码
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
编译代码
$ cd ~/catkin_ws
$ catkin_make
打开另一个终端,启动talker.py
rosrun beginner_tutorials talker.py
rostopic echo /chatter
8.编写订阅者节点:
roscd beginner_tutorials/scripts/
touch listener.py
chmod +x 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():
#定义节点的名字叫listener,
#anonymous=True生成一个随机数保证名字唯一
rospy.init_node('listener', anonymous=True)
#订阅函数,订阅chatter主题,内容类型是std_msgs.msgs.String
#当有新内容,调用callback函数处理。接受到的主题内容作为参数传递给callback.
rospy.Subscriber('chatter', String, callback)
#rospy.spin()只是不让你的节点退出,直到节点被明确关闭
rospy.spin()
if __name__ == '__main__':
listener()
编译代码
$ cd ~/catkin_ws
$ catkin_make
9.测试代码:
打开新终端,启动roscore
roscore
先打开终端运行talker.py, 打开另一个终端,启动listener.py
rosrun beginner_tutorials listener.py
使用rqt_console命令查看日志输出
rqt_console
10.制作Launch文件:
一次性启动多个ROS节点,以及配置参数
<launch>
<node name="talker" pkg="beginner_tutorials" type="talker.py" />
<node name="listener" pkg="beginner_tutorials" type="listener.py" />
launch>
首先用launch标签开头,以表明这是一个launch文件。
运行launch
roslaunch beginner_tutorials talker-and-listener.launch