暑假学习笔记——ROS

一. 创建工作空间

1.工作空间的创建

mkdir catkin_ws

mkdir src

cd /catkin_ws/src

catkin_init_workspace

2.编译工作空间

需要在()_ws的文件下下进行编译

catkin_make

3.设置环境变量

source devel/setup.bash

4.检查环境变量

echo $ROS_PACKAGE_PATH

二.创建功能包

1.创建功能包

在src文件下创建功能包,<package_name> 是新功能包的名称,[depend1] [depend2] [depend3] 是可选的依赖项。

catkin_create_pkg <文件名> [depend1] [depend2] [depend3]

如:catkin_creat_pkg test_pkg std_msgs rospy roscpp

2.编译功能包

catkin_make

source /catkin_ws/devel/setup.bash

三.发布者Publisher和订阅者Subscriber

一个ROS话题包括一个消息类型和一个话题名称。在ROS中,消息类型定义了消息的结构和类型,而话题名称则用于标识特定的话题。一个节点可以同时发布和订阅多个话题。节点可以发布消息到多个话题,同时也可以订阅来自多个话题的消息。

当一个节点发布一个消息到话题时,所有订阅该话题的节点都会接收到该消息。一个节点可以通过ROS Master(ROS主节点)来发现其他节点发布的话题,并向其订阅。通过这种方式,ROS节点可以轻松地共享数据和信息。

(一).发布者Publisher和订阅者Subscriber

1.(1).发布者一般步骤

(2).订阅者一般步骤

2.配置CMakeList.txt的编译规则

  • 设置需要编译的代码和生成的可执行文件
  • 设置链接库

在CMakeList.txt中的install的上方添加以下

add_executable(节点名 .cpp文件地址)#从工作空间src开始:/src/xxxx/xxx.cpp   #运行
target_link_libraries(节点名 ${catkin_LIBRARIES})                        #库连接

(2)add_executable:用于设置需要编译的代码和生成的可执行文件。第一个参数为期望生成的可执行文件的名称,后边的参数为参与编译的源码文件(cpp),如果需要多个代码文件,则可
在后面依次列出,中间用空格进行分隔。
(3)target_link_libraries:用于设置链接库。很多功能需要使用系统或者第三方的库函数,通过该选项可以配置执行文件链接的库文件,第一个参数是可执行文件的名称,后面依次列出需要链接的库。此处编译没有使用其他库,添加默认链接库${catkin_LIBRARIES}即可。

3.进行编译运行,在编译后需要进行环境变量的设置,在每次运行之前都需要配置环境。

另一种方法在主目录中 .bashrc中最后添加下图命令,就不需要重新配置环境。

 source ~/catkin_ws/devel/setup.bash

在CMakeList.txt中的install的上方添加以下

add_executable(节点名 .cpp文件地址)#从工作空间src开始:/src/xxxx/xxx.cpp   #运行
target_link_libraries(节点名 ${catkin_LIBRARIES})                        #库连接

 最后运行,如果使用c++来编写,需要进行编译后运行,若是用python,就不用编译,但是需要将python文件中的属性中的允许作为程序执行文件打开

方法一:

  方式二:使用命令行,cd到该文件的路径下,然后输入以下命令:

$ chmod +x name.py

在终端中输入roscore,rosrun运行
 

(二).自定义话题

1.定义msg文件

在catkin_ws/src/中相应功能包下创建文件夹msg,该文件用于存储.msg文件,注意此文件是与编程语言无关的。/.msg文件中的内容相当于是宏定义。

2.在package.xml中添加功能包依赖

3.在CMakeLists.txt中添加编译选项

4.编译生成文件

 在catkin_ws中进行编译,编译成功后会在catkin_ws中的devel下面的include生成文件,里面存放了编译成功后的头文件

5.发布者和订阅者的一般步骤

6.配置CMakeLists.txt中的编译规则

  • 设置需要编译的代码和可执行文件
  • 设置链接库
  • 添加依赖项

在CMakeLists.txt中install上方添加依赖项

add_executable(节点名 .cpp文件地址)#从工作空间src开始:/src/xxxx/xxx.cpp   #运行
target_link_libraries(节点名 ${catkin_LIBRARIES})                        #库连接

add_dependencies(节点名 ${PROJECT_NAME}_generate_messages_cpp)    #连接依赖,与自定义消息连接


(4)add_dependencies:用于设置依赖。在很多应用中,我们需要定义语言无关的消息类型,消息类型会在编译过程中产生相应语言的代码,如果编译的可执行文件依赖这些动态生成的代码,则
需要使用add_dependencies添加${PROJECT_NAME}_generate_messages_cpp配置,即该功能包动态产生的消息代码。该编译规则也可以添加其他需要依赖的功能包。

7.编译运行

同发布者Publisher和订阅者Subscriber中编译运行相同。

四.客户端Client和服务端service

服务端是一个ROS节点,它通过定义一个服务来提供一个特定的功能。服务通常由一个请求和一个响应组成,并且可以使用不同的数据类型作为它们的参数和返回值。

客户端是另一个ROS节点,它可以请求一个或多个服务。当客户端请求一个服务时,它会发送一个请求消息给服务端,并等待服务端返回一个响应消息。客户端可以通过ROS的API来发送请求和接收响应,并且可以使用不同的编程语言来实现。

在ROS中,服务端和客户端之间的通信通常使用ROS的消息传递机制,这可以确保数据的可靠传输和类型匹配。当一个服务端启动时,它会向ROS的主节点注册自己提供的服务,客户端可以通过查询主节点来找到它需要的服务。

(一).客户端和服务端

1.一般步骤

客户端

服务端

 

2.配置CMakeLists.txt的编译规则

  • 设置需要编译的代码和生成的可执行文件
  • 设置链接库

在CMakeList.txt中的install的上方添加以下

add_executable(节点名 .cpp文件地址)#从工作空间src开始:/src/xxxx/xxx.cpp   #运行
target_link_libraries(节点名 ${catkin_LIBRARIES})                        #库连接

 3.编译运行客户端和服务端

如果使用c++来编写,需要进行编译后运行,若是用python,就不用编译,但是需要将python文件中的属性中的允许作为程序执行文件打开,在终端中输入roscore,rosrun运行。

(二).服务数据的定义

1.定义srv文件

2.在package.xml中添加功能包依赖2.在package.xml中添加功能包依赖

在如下图所示的位置上添加依赖

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

 3.在CMakeLists.txt添加编译选项

 4.编译生成语言相关文件

在catkin_ws中进行编译,编译成功后会在catkin_ws中的devel下面的include生成文件,里面存放了编译成功后的头文件

5.创建服务器、客户端代码一般步骤

5.配置CMakeLists.txt中的编译规则

  • 设置需要编译的代码和可执行文件
  • 设置链接库
  • 添加依赖项

在CMakeLists.txt中install上方添加依赖项

add_executable(节点名 .cpp文件地址)#从工作空间src开始:/src/xxxx/xxx.cpp   #运行
target_link_libraries(节点名 ${catkin_LIBRARIES})                        #库连接

add_dependencies(节点名 ${PROJECT_NAME}_generate_messages_cpp)    #连接依赖,与自定义消息连接

 7.编译运行

同客户端和服务端相同。

五.参数

1.参数的命令行

2.一般步骤 

3.配置CMakeLists.txt

同发布订阅,服务客户端的规则相同。

4.编译运行

六.tf坐标系广播与监听

1.创建功能包

 2.编写的一般步骤

(1)tf广播器

 (2)tf监听器

 

3.配置CMakeLists.txt

同发布订阅,服务客户端的规则相同。

4.编译运行

七.launch

1.文件语法

launch:launch文件中的根元素采用<launch>标签定义

node:

①pkg 节点功能包名称。

②type 节点可执行文件名称。

③name 节点运行时名称。

④args 局部变量。

<remap>:节点重映射ROS计算图资源的命名

<include>:包含其他文件(类似头文件)。

等等

八.action

ROS的Action是一个机制,用于在机器人系统中进行长时间运行的任务。与ROS中的service类似,一个Action也是一种服务器/客户端模型,其中客户端可以请求在后台执行长时间运行的任务,服务器可以像服务一样响应这些请求。但是,与service不同的是,Action允许客户端在执行任务的过程中获取中间结果,取消任务,或者在必要时调整任务的目标。

1.动作规范

①goal:用于向服务器发送目标。
 
②cancel :用于向服务器发送取消请求。
 
③status :用于通知客户端系统中每个目标的当前状态。
 
④feedback :用于周期反馈目标的辅助信息。
 
⑤result :用于向client发送任务的执行结果,这个topic只会发布一次。

 自定义 action

动作定义文件中包含了动作的目标,结果,和反馈的消息格式。通常放在 package 的 action 文件夹下,文件扩展名为.action

1.定义action文件

int32 requestnumber
---
int32 resultnumber
---
int32 feedbacknumber

2.在package.xml中添加功能包依赖

<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
  <exec_depend>actionlib_msgs</exec_depend>
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

3.在CMakeLists.txt文件中添加如下的编译规则

add_action_files(DIRECTORY action FILES checkaction.action)
generate_messages(DEPENDENCIES std_msgs actionlib_msgs )

find_package(catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs message_generation  actionlib_msgs  actionlib)

4.编译生成语言相关文件

在catkin_ws中进行编译,编译成功后会在catkin_ws中的devel下面的include生成文件,里面存放了编译成功后的头文件

5.编写action服务端与客户端代码

客户端

  • 定义一个客户端
  • 等待服务端
  • 创建action的goal
  • 发送action的goal给服务端,并设置回调函数,回调函数并处理信息

服务端

  • 定义服务器,
  • 运行服务器
  • 收到action的goal后回调回调函数
  • action完成后,向客户端返回结果

6.编译运行

与服务端与客户端方法类似

九.作业

(1) 实验 1: 使用 ROS 话题(Topic) 机制实现消息发布与订阅

要求: 编写代码实现 ROS 中消息的发布与订阅: 创建一个发布者,每隔 100ms 依次发送斐波拉契数列的数字到话题 `/fibonacci` 中; 创建一个订阅者,订阅该话题,输出订阅结果。如,订阅者依次输出: 1 1 2 3 5 8 ··

发布者pyhton

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#导入rospy模块
import rospy
from std_msgs.msg import Int32
#创建发布者
def fibonacci_publisher():
	# ROS节点初始化
    rospy.init_node('fibonacci_publisher', anonymous=True)
    # 创建发布者,发布 Fibonacci 消息到话题 /fibonacci,消息类型为std_msgs.msg::Int32,队列长度10
    pub = rospy.Publisher('/fibonacci', Int32, queue_size=10)
	#设置循环的频率
    rate = rospy.Rate(10)
    a=0
    b=1
    msg = Int32()
    while not rospy.is_shutdown():
        c=a+b
        a=b
        b=c
        msg.data=a
		# 发布消息
        pub.publish(msg)
        rospy.loginfo("发布的数据 %s",msg.data)

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

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

订阅者python

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
#回调函数
def callback(msg):
    rospy.loginfo(msg.data)
#创建订阅信息
def fibonacci_subscriber():
   #ROS节点初始化
    rospy.init_node('fibonacci_subscriber', anonymous=True)
   #创建一个subscriber,订阅名为/fibonacci的topic,注册回调函数
    rospy.Subscriber("/fibonacci",Int32,callback)
   #循环等待回调函数
    rospy.spin()

if __name__ == '__main__':
    fibonacci_subscriber()

(2) 实验 2: 使用 ROS 服务(Service) 机制实现同步请求与答复

要求: 编写代码实现 ROS 中的服务请求与答复: 创建服务端,注册 Service,当服务端收到客户端 Service 请求(携带整型参数 a.b) 后,服务端返回 a.b 的和给客户端,客户端输出结果。如,客户端给服务端 Service 发送参数 3,9,服务端返回 12,客户端输出: 12。

客户端python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import rospy

from learning_service.srv import AddTwoInts,AddTwoIntsResponse

def add_client(a,b):
    #ROS节点初始化
    rospy.init_node('add_client')
    #发现add_服务后,创建一个服务客户端,连接名为add_的service
    rospy.wait_for_service('add_')
    try:
        add1 = rospy.ServiceProxy('add_', AddTwoInts)
        #请求服务调用,输入请求数据
        response = add1(a,b)
        #返回两者数之和
        return response
    except rospy.ServiceException, e:
        print "服务失败: %s"%e

if __name__ == "__main__":
    if len(sys.argv) == 3:
        a = sys.argv[1]
        b = sys.argv[2]
    else:
        sys.exit(1)
	#服务调用并显示调用结果
    print("Requesting %s+%s" % (int(a),int(b)))
    print "Show result : %s" %(add_client(int(a),int(b)))

rospy.wait_for_service("service名称")可以使得该client_node节点直到对应service服务器开始工作之后,代码才继续往下运行
启动client的函数接口:rospy.ServiceProxy("service名称",自定义srv数据类型)

服务端python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import rospy
from learning_service.srv import AddTwoInts,AddTwoIntsResponse
def doNum(request):
    a=request.A
    b=request.B
    # 求和
    c = a+b
    response = AddTwoIntsResponse(c)     # 创建一个response对象类型是AddIntsResponse
    #显示请求数据
    rospy.loginfo("服务器接收到的请求数据是:a=%d,b=%d,结果是c=%d",a,b,c)
    #反馈数据
    return response

if __name__=="__main__":
    #ROS节点初始化
    rospy.init_node('add_server')
    #创建一个名为add_的server,注册回调函数
    server=rospy.Service('add_',AddTwoInts,doNum)
    rospy.loginfo("服务器启动成功")
    #循环等待回调函数
    rospy.spin()

启动服务的函数接口:rospy.Service("service名", srv数据类型, 回调函数)
回调函数中传入的是请求request,返回的是response
返回的数据类型是自定义的
 

(3) 实验 3: 使用 ROS 动作(Action) 机制实现目标请求、进度与完成结果的反馈。

要求: 编写代码实现 ROS 中动作请求与进度反馈,创建服务端,注册 Action,客户端发送 action 请求检测 40 个零件,服务端接收后,每隔 1s 测一个零件 (每检测一个打印一次),实时给客户端返回检测进度(客户端打印进度百分比),并在检测完毕时告知客户端目标完成。如,服务端实时打印: 检测 1 个零件 检测 2 个零件 ... 检测 40 个零件 检测完成,客户端实时打印: 2.5% 5% ... 100% 检测完成

客户端python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import actionlib
from std_msgs.msg import Float32
from learning_action.msg import checkactionAction,checkactionResult, checkactionGoal
class checkactionClient:
    def __init__(self):
        # 创建动作客户端
        self.client = actionlib.SimpleActionClient('checkaction', checkactionAction)
        self.client.wait_for_server()
        # 订阅进度消息
        rospy.Subscriber('checkaction_progress',Float32, self.progress_callback)
    
    def progress_callback(self, feedback):
        
        self.progress=feedback.data*100
        # 返回结果后,打印信息
        rospy.loginfo('Progress: %.2f%%', self.progress)

    def send_action_request(self):
        goal = checkactionGoal()
        # 将回调函数作为feedback_cd关键词的参数,传入 send_geal,完成回调的注册
        self.client.send_goal(goal, feedback_cb=self.progress_callback)
        self.client.wait_for_result()


if __name__ == '__main__':
    # ROS节点初始化
    rospy.init_node('checkaction_client')
    # 创建客户端
    client = checkactionClient()
    client.send_action_request()

服务端python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import actionlib
from std_msgs.msg import Float32
from learning_action.msg import checkactionAction,checkactionResult, checkactionGoal

class checkactionServer:
    def __init__(self):
        #创建了一个名为“checkaction”的简单动作服务器,它的类型是“checkactionAction”,以及回调函数,参数False
        self.server = actionlib.SimpleActionServer('checkaction', checkactionAction, self.execute, False)
        # 启动服务器
        self.server.start()
        # 创建进度发布者
        self.progress_pub = rospy.Publisher('checkaction_progress', Float32, queue_size=10)
    #执行函数
    def execute(self, goal):
        #每秒检测
        rate = rospy.Rate(1)
        success = True
        # 检测零件
        for i in range(1, 41):
            if self.server.is_preempt_requested():
                
                self.server.set_preempted()
                success = False
                break
            # 发布进度
            self.progress_pub.publish(i/40.0)
            #打印信息
            rospy.loginfo('checkaction part %d', i)
            rate.sleep()
        if success:
            # 发布结果
            self.server.set_succeeded(checkactionResult())

if __name__ == '__main__':
    #ROS节点初始化
    rospy.init_node('checkaction_server')
    # 创建服务器
    server = checkactionServer()
    # 运行节点
    rospy.spin()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值