前言

之前写过一篇关于ROS学习笔记,那时候刚开始学感觉不适合现在使用所以重写一篇。

这篇文章缩减了一部分不需要的内容,关于实操应用的内容可以看下一篇文章

基础知识

工作空间和功能包的基本操作

创建工作空间目录和代码空间

1
2
3
4
5
6
7
8
mkdir ros_learning
cd ros_learning
mkdir src
cd src
catkin_init_workspace
cd ..
catkin_make
catkin_make install

环境变量设置

在工作空间目录内:

1
source devel/setup.bash

检查环境变量:

1
echo $ROS_PACKAGE_PATH

每次打开终端都要设置环境变量,如果想要免除这一步骤可以修改用户目录内的(/home/triority)文件.bashrc

source /opt/ros/melodic/setup.bash下一行加入:

1
source /home/triority/desktop/ROS_learning/devel/setup.bash

工作空间路径改成自己的。

创建功能包:catkin_create_pkg

src文件夹内:

1
catkin_create_pkg <包名> <依赖>

依赖:roscpp;用于编写c++程序,rospy:用于编写python程序,std_msgs;ros标准消息结构,等依赖的的一个名为lab的功能包(应创建在src文件夹内)

1
catkin_create_pkg lab roscpp rospy std_msgs geometry_msgs turtlesim message_generation

话题:发布与订阅

自定义消息

消息定义

在功能包文件夹内创建msg文件夹,并新建lab.msg文件,在里面写入:

1
string str
添加依赖

package.xml文件内添加依赖:

1
2
<exec_depend>message_runtime</exec_depend>
<build_export_depend>message_generation</build_export_depend>

CMakeLists.txt内加入:

1
2
3
4
5
6
7
8
9
add_message_files(
FILES
Person.msg
)

generate_messages(
DEPENDENCIES
std_msgs
)

并把

1
#  CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim

改为

1
CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime

Publisher

publisher.py
记得给.py文件添加可执行权限!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
from lab.msg import lab


def publisher():
# 初始化ROS节点
rospy.init_node('lab_publisher_node', anonymous=True)

# 创建一个Publisher,发布名为/publisher_info的topic,消息类型为lab,队列长度10
publisher_info = rospy.Publisher('/publisher_info', lab, queue_size=10)

#设置循环的频率
rate = rospy.Rate(1)

while not rospy.is_shutdown():
# 初始化消息类型
lab_msg = lab()
lab_msg.str = "Tom"

# 发布消息
publisher_info.publish(lab_msg)
rospy.loginfo("Publsh person message[%s]", lab.str)

# 按照循环频率延时
rate.sleep()


if __name__ == '__main__':
try:
publisher()
except rospy.ROSInterruptException:
pass

Subscriber

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
from lab.msg import lab


def InfoCallback(msg):
rospy.loginfo("Subcribe Info: str:%s", msg.str)


def subscriber():
# ROS节点初始化
rospy.init_node('lab_subscriber', anonymous=True)

# 创建一个Subscriber,订阅名为/publisher_info的topic,注册回调函数InfoCallback
rospy.Subscriber("/publisher_info", lab, InfoCallback)

# 循环等待回调函数
rospy.spin()


if __name__ == '__main__':
subscriber()

rosrun

1
rosrun lab publisher.py
1
rosrun lab subscriber.py

服务:服务端与客户端

自定义消息

新建srv文件夹并写入labs.srv(不能与前面的lab.msg同名):

1
2
3
string str
---
string res

package.xml添加的依赖和前面的话题部分一样,写过就不再写了:

1
2
<exec_depend>message_runtime</exec_depend>
<build_export_depend>message_generation</build_export_depend>

CMakeList.txt添加:

1
2
3
4
add_service_files(
FILES
Person.srv
)

还需要添加的另一部分也已经在前面的话题部分一样:

1
2
3
4
generate_messages(
DEPENDENCIES
std_msgs
)

Client

client.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
from lab.srv import labs, labsResponse


def client():
# ROS节点初始化
rospy.init_node('lab_client')

# 发现/lab_server服务后,创建客户端连接名为/lab_server的service
rospy.wait_for_service('/lab_server')
try:
person_client = rospy.ServiceProxy('/lab_server', labs)

# 请求服务调用,输入请求数据
response = person_client("str")
return response.res
except rospy.ServiceException as e:
print ("Service call failed: %s"%e)

if __name__ == "__main__":
#服务调用并显示调用结果
print ("Show result : %s" %(client()))

Server

server.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
from lab.srv import labs, labsResponse


def Callback(req):
# 显示请求数据
rospy.loginfo("string: str:%s", req.str)

# 反馈数据
return labsResponse("OK")


def person_server():
# ROS节点初始化
rospy.init_node('lab_server')

# 创建一个名为/lab_server的server,注册回调函数Callback
s = rospy.Service('/lab_server', labs, Callback)

# 循环等待回调函数
print ("Ready to show.")
rospy.spin()

if __name__ == "__main__":
person_server()

rosrun

1
rosrun lab client.py
1
rosrun lab server.py

TF坐标变换

参数服务器:全局字典

参数操作命令行

1.列出参数

1
rosparam list

2.获取参数值

1
rosparam get <参数>

3.修改参数

1
rosparam set <参数>

4.保存参数为文件

1
rosparam dump xxx.yaml

5.从文件加载参数

1
rosparam load xxx.yaml

6.删除参数

1
rosparam delete xxx.yaml

使用python操作参数

parameter_config.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import rospy
from std_srvs.srv import Empty


def parameter_config():
# ROS节点初始化
rospy.init_node('parameter_config', anonymous=True)

# 读取背景颜色参数
red = rospy.get_param('/turtlesim/background_r')
green = rospy.get_param('/turtlesim/background_g')
blue = rospy.get_param('/turtlesim/background_b')

rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)

# 设置背景颜色参数
rospy.set_param("/turtlesim/background_r", 255);
rospy.set_param("/turtlesim/background_g", 255);
rospy.set_param("/turtlesim/background_b", 255);

rospy.loginfo("Set Backgroud Color[255, 255, 255]");

# 读取背景颜色参数
red = rospy.get_param('/turtlesim/background_r')
green = rospy.get_param('/turtlesim/background_g')
blue = rospy.get_param('/turtlesim/background_b')

rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)

# 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
rospy.wait_for_service('/clear')
try:
clear_background = rospy.ServiceProxy('/clear', Empty)

# 请求服务调用,输入请求数据
response = clear_background()
return response
except rospy.ServiceException as e:
print ("Service call failed: %s"%e)

if __name__ == "__main__":
parameter_config()

使用launch文件启动

luanch文件语法

根元素定义标签
启动节点
1
<node pkg="package-name" type="executable-name" name="node-name" />

可选属性:

  • pkg:节点功能包名称
  • type:节点可执行文件名称
  • name:节点运行时的名称,取代原有节点名,避免冲突
  • output:控制终端使出
  • respawn:挂掉后是否自动重启
  • required:是否为必须项
  • args:输入参数
  • ……
设置参数服务器的参数
1
<param name="output_frame" value="odom" />

name:参数名;value:参数值

加载多个参数:

1
<rosparam file+"param.yaml" command="load" ns="params" />
launch文件内局部变量
1
<arg name="arg-name" default="arg-value" />

name:参数名;value:参数值

重命名
1
<remap from="/turtlebot/cmd_vel" to+"/cmd_vel" />
包含其他launch文件

运行launch文件

1
roslaunch <package_name> <launch_name>

命令行及可视化工具

可视化查看节点关系rqt_graph
1
rqt_graph
查看节点信息rosnode

查看全部节点

1
rosnode list

查看节点详细信息

1
rosnode info <节点名>
查看话题rostopic

打印话题列表

1
rostopic list

给话题发布数据

1
rostopic pub <话题名> <数据内容>

数据内容可用两次tab补全默认格式。可加参数 -r <频率(Hz)> 来连续发布

查看消息rosmsg

查看消息数据结构

1
rosmsg show <话题名>
查看服务rosservice

#查看所有服务

1
rosservice list

发布服务请求

1
rosservice call <服务名>
记录工具

记录话题数据

1
rosbag record -a -O <压缩数据包名>

其中-a表示all保存全部数据,-O表示保存成压缩包

复现话题数据

1
rosbag paly <复现文件名>
rqt可视化

显示tf坐标变换关系:

1
rosrun rqt_tf_tree rqt_tf_tree

日志输出工具rqt_console
计算图可视化工具rqt_graph
数据绘图工具rqt_plot
图像渲染工具rqt_image_view