一、ROS 安装
(一)准备工作
- 确认系统版本:咱得先搞清楚,ROS 有好几个版本,每个版本跟 Ubuntu 系统版本是对应的。比如说,Melodic 版本对应的是 Ubuntu 18.04,Noetic 版本对应的是 Ubuntu 20.04。所以安装之前,先看看自己的 Ubuntu 系统版本,是不是和想装的 ROS 版本匹配。
- 设置软件源:打开终端,咱要编辑一下软件源列表。要是你在国内,建议用国内的镜像源,像清华大学的镜像源就不错,下载速度能快不少。找到/etc/apt/sources.list这个文件,把镜像源地址添加进去就行。
(二)安装步骤
- 添加 ROS 软件源:在终端里输入这行命令,就能把 ROS 官方软件源添加进去。
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
- 设置密钥:再输入下面这行命令,设置一下 ROS 软件源的密钥。
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
- 更新软件包列表:执行sudo apt update这个命令,更新一下系统的软件包列表,这样就能获取到最新的软件包信息啦。
- 安装 ROS:安装的时候可以根据自己的需求来选,是装完整版本还是桌面版。要是想装完整版本(里面包含了所有功能包),就用这个命令:
sudo apt install ros-$ROS_DISTRO-desktop-full
要是只想装桌面版(常用功能包都有),把命令里的desktop-full改成desktop就行。比如说,要装 Noetic 版本的桌面版,命令就是:
sudo apt install ros-noetic-desktop
- 初始化 rosdep:rosdep 是 ROS 里用来管理依赖的工具,装完 ROS 之后,得把它初始化一下。输入下面这两个命令:
sudo rosdep init
rosdep update
- 设置环境变量:为了让系统能识别 ROS 命令,还得设置一下环境变量。在终端里输入这行命令,就能把 ROS 环境变量添加到当前用户的 bashrc 文件里:
echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc
source ~/.bashrc
- 安装 rosinstall:rosinstall 是个常用的 ROS 命令行工具,能从版本控制系统里下载多个 ROS 功能包。用下面这个命令安装:
sudo apt install python3-rosinstall python3-rosinstall-generator python3-wstool build-essential
二、话题(Topic)
(一)概念
话题是 ROS 里最基本的一种通信方式,它用的是发布 / 订阅模式,也就是 Publish/Subscribe,简称 Pub/Sub。简单来说,就是有些节点可以往特定的话题里发消息,另外一些节点可以订阅这个话题,接收消息。比如说,在机器人导航系统里,激光雷达节点就可以把激光扫描的数据发布到/scan这个话题上,导航节点订阅/scan话题,就能拿到这些数据,用来规划路径。
(二)工作原理
- 发布者(Publisher):发布者就是往特定话题发消息的节点。它先创建一个消息对象,把消息内容填好,然后调用 ROS 的发布函数,就把消息发到指定话题上去了。
- 订阅者(Subscriber):订阅者是从特定话题接收消息的节点。它得先注册一个回调函数,只要有新消息发布到它订阅的话题上,ROS 就会自动调用这个回调函数,把收到的消息传给回调函数去处理。
(三)示例代码(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():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
rospy.spin()
if __name__ == '__main__':
listener()
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)
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
三、服务(Service)
(一)概念
服务是 ROS 里的另一种通信方式,它用的是客户端 / 服务器模式,也就是 Client/Server,简称 C/S。和话题的异步通信不一样,服务是同步通信。啥意思呢?就是客户端向服务器发请求,服务器处理完请求,再把响应返回给客户端。比如说,在控制机器人手臂的时候,客户端可以把目标位置的请求发给服务器,服务器收到请求后,控制机器人手臂运动,最后把操作结果返回给客户端。
(二)工作原理
- 服务器(Server):服务器节点得定义一个服务回调函数,只要收到客户端的请求,就会调用这个回调函数来处理。处理完之后,服务器把响应发给客户端。
- 客户端(Client):客户端节点创建一个服务请求对象,把请求内容填好,然后调用 ROS 的服务调用函数,向服务器发送请求。发完请求之后,客户端会一直等着,直到收到服务器的响应。
(三)示例代码(Python)
# 服务器端代码
import rospy
from beginner_tutorials.srv import AddTwoInts, AddTwoIntsResponse
def handle_add_two_ints(req):
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()
# 客户端代码
import sys
import rospy
from beginner_tutorials.srv import AddTwoInts
def add_two_ints_client(a, b):
rospy.wait_for_service('add_two_ints')
try:
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
resp1 = add_two_ints(a, b)
return resp1.sum
except rospy.ServiceException as e:
print("Service call failed: %s" % e)
def usage():
return "%s [a b]" % sys.argv[0]
if __name__ == "__main__":
if len(sys.argv) == 3:
a = int(sys.argv[1])
b = int(sys.argv[2])
else:
print(usage())
sys.exit(1)
print("Requesting %s+%s" % (a, b))
print("%s + %s = %s" % (a, b, add_two_ints_client(a, b)))
四、动作(Action)
(一)概念
动作是 ROS 里用来处理长时间运行任务的一种通信机制,它结合了话题和服务的特点。动作包含三个部分:目标(Goal)、反馈(Feedback)和结果(Result)。比如说机器人导航的时候,客户端把目标位置的请求(Goal)发给导航节点,导航节点在导航过程中,会定期把当前位置和状态的反馈(Feedback)发给客户端,等导航完成了,再把最终结果(Result)返回给客户端。
(二)工作原理
- 动作客户端(Action Client):动作客户端创建一个目标对象,发给动作服务器。同时,它还能注册反馈回调函数和结果回调函数,用来接收服务器发过来的反馈和结果。
- 动作服务器(Action Server):动作服务器接收客户端发的目标