ROS-noetic自定义action文件进行通信

前言

        本系统的系统是Ubuntu20.04的ros-noetic,本文讲述了通过创建 ROS 节点(服务器和客户端)的完整流程,使用 Action 实现从 1 到 N 的累加和,并在计算过程中向客户端发送进度反馈。

 整体概述

  1. 创建功能包:用来包含 Action 文件及其相关依赖。
  2. 定义 Action 文件:在.action文件中定义目标、结果和反馈。
  3. 修改配置文件:编辑CMakeLists.txt 和package.xml 以包含 Action 文件和依赖。
  4. 编写服务端和客户端:服务端实现累加逻辑并发布进度反馈,客户端发送请求并处理响应。
  5. 运行:通过 ROS Master、服务端和客户端来测试整个流程

过程

1. 创建功能包

        首先我们需要在catkin_ws/src目录下创建一个新的功能包,命名为demo_action,它将包含Action相关的代码和文件。如果没有catkin_ws的文件的话,就自己创建一下吧。

mkdir -p catkin_ws/src
catkin_make
cd ~/catkin_ws/src
catkin_create_pkg demo_action actionlib actionlib_msgs roscpp rospy std_msgs

2.创建Action文件

cd demo_action
mkdir action

        在action目录下创建名为AddInts.action的文件:

touch AddInts.action

        打开AddInts.action文件,添加以下内容:

#目标值
int32 num
---
#最终结果
int32 result
---
#连续反馈
float64 progress_bar

        这个文件中定义了请求的目标值num,最终的响应结果result,以及来纳许反馈的进度progress_bar。

3.编辑配置文件

        修改CMakeLists.txt,在功能包的根目录下,编辑CMakeLists.txt文件。

cd ~/catkin_ws/src/demo_action
sudo nano CMakeLists.txt

        找到find_package部分,添加actionlib和actionlib_msgs,修改完如下:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  actionlib
  actionlib_msgs
)

        再在下面添加add_action_files,指向.action文件。

add_action_files(
  FILES
  AddInts.action
)

        生成消息和动作文件。

generate_messages(
  DEPENDENCIES
  std_msgs
  actionlib_msgs
)

        在catkin_pachage部分声明依赖。

catkin_package(
  CATKIN_DEPENDS roscpp rospy std_msgs actionlib actionlib_msgs
)

        添加完如下图。

 

4.修改package.xml文件

        在package.xml中,添加以下依赖项声明。

<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>

        添加完如下图。

5.案例测试 

        现在使用一个简单的测试程序来测试一下是否能够正常使用。

        在demo_action/src目录中创建add_ints_server.py和add_ints_client.py文件:

cd ~/catkin_ws/src/demo_action/src
touch add_ints_server.py
sudo nano add_ints_server.py

        将server的代码复制粘贴进去:

#!/usr/bin/env python
import rospy
import actionlib
from demo_action.msg import AddIntsAction, AddIntsResult, AddIntsFeedback

class AddIntsActionServer:
    def __init__(self):
        self.server = actionlib.SimpleActionServer('add_ints', AddIntsAction, self.execute, False)
        self.server.start()

    def execute(self, goal):
        result = AddIntsResult()
        feedback = AddIntsFeedback()

        total_sum = 0
        for i in range(1, goal.num + 1):
            total_sum += i
            feedback.progress_bar = float(i) / goal.num
            self.server.publish_feedback(feedback)
            rospy.sleep(0.5)  # Simulate a delay

        result.result = total_sum
        self.server.set_succeeded(result)

if __name__ == '__main__':
    rospy.init_node('add_ints_server')
    server = AddIntsActionServer()
    rospy.spin()

        然后是client的代码。

#!/usr/bin/env python
import rospy
import actionlib
from demo_action.msg import AddIntsAction, AddIntsGoal

def feedback_cb(feedback):
    rospy.loginfo('Progress: %f' % feedback.progress_bar)

def add_ints_client():
    client = actionlib.SimpleActionClient('add_ints', AddIntsAction)
    client.wait_for_server()

    goal = AddIntsGoal(num=10)
    client.send_goal(goal, feedback_cb=feedback_cb)
    client.wait_for_result()

    return client.get_result()

if __name__ == '__main__':
    rospy.init_node('add_ints_client')
    result = add_ints_client()
    rospy.loginfo('Result: %d' % result.result)

        要确保这两个文件可执行:

chmod +x add_ints_server.py add_ints_client.py

        返回catkin_ws根目录,编译功能包:

cd ~/catkin_ws
catkin_make

        然后启动。

source devel/setup.bash

        启动Action服务器和客户端。

roscore

        启动 Action 服务器:

rosrun demo_action add_ints_server.py

        启动 Action 客户端:

rosrun demo_action add_ints_client.py

        这样就可以测试服务器和客户端是否能正常通信了。

6. 实际测试

        过程和上述的是一样的,我在这里就直接放入代码了。

server.py

#! /usr/bin/env python
import rospy
import actionlib
from demo01_action.msg import *
"""
    需求:
        创建两个ROS 节点,服务器和客户端,
        客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,
        这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,
        又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,
        为了良好的用户体验,需要服务器在计算过程中,
        每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。
    流程:
        1.导包
        2.初始化 ROS 节点
        3.使用类封装,然后创建对象
        4.创建服务器对象
        5.处理请求数据产生响应结果,中间还要连续反馈
        6.spin
"""

class MyActionServer:
    def __init__(self):
        #SimpleActionServer(name, ActionSpec, execute_cb=None, auto_start=True)
        self.server = actionlib.SimpleActionServer("addInts",AddIntsAction,self.cb,False)
        self.server.start()
        rospy.loginfo("服务端启动")


    def cb(self,goal):
        rospy.loginfo("服务端处理请求:")
        #1.解析目标值
        num = goal.num
        #2.循环累加,连续反馈
        rate = rospy.Rate(10)
        sum = 0
        for i in range(1,num + 1):
            # 累加
            sum = sum + i
            # 计算进度并连续反馈
            feedBack = i / num
            rospy.loginfo("当前进度:%.2f",feedBack)

            feedBack_obj = AddIntsFeedback()
            feedBack_obj.progress_bar = feedBack
            self.server.publish_feedback(feedBack_obj)
            rate.sleep()
        #3.响应最终结果
        result = AddIntsResult()
        result.result = sum        
        self.server.set_succeeded(result)
        rospy.loginfo("响应结果:%d",sum)
if __name__ == "__main__":
    rospy.init_node("action_server_p")
    server = MyActionServer()
    rospy.spin()

client.py

#! /usr/bin/env python

import rospy
import actionlib
from demo01_action.msg import *

"""
    需求:
        创建两个ROS 节点,服务器和客户端,
        客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,
        这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,
        又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,
        为了良好的用户体验,需要服务器在计算过程中,
        每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。
    流程:
        1.导包
        2.初始化 ROS 节点
        3.创建 action Client 对象
        4.等待服务
        5.组织目标对象并发送
        6.编写回调, 激活、连续反馈、最终响应
        7.spin
"""

def done_cb(state,result):
    if state == actionlib.GoalStatus.SUCCEEDED:
        rospy.loginfo("响应结果:%d",result.result)

def active_cb():
    rospy.loginfo("服务被激活....")


def fb_cb(fb):
    rospy.loginfo("当前进度:%.2f",fb.progress_bar)

if __name__ == "__main__":
    # 2.初始化 ROS 节点
    rospy.init_node("action_client_p")
    # 3.创建 action Client 对象
    client = actionlib.SimpleActionClient("addInts",AddIntsAction)
    # 4.等待服务
    client.wait_for_server()
    # 5.组织目标对象并发送
    goal_obj = AddIntsGoal()
    goal_obj.num = 10
    client.send_goal(goal_obj,done_cb,active_cb,fb_cb)
    # 6.编写回调, 激活、连续反馈、最终响应
    # 7.spin
    rospy.spin()

        如果运行成功的话,就会如下图的显示。

结语 

         在本文中,创建了一个基于 ROS 的 Action 通信示例,包括一个服务器和一个客户端。服务器能够接收来自客户端的整数输入,并计算从 1 到 N 的和。服务器在计算过程中实时反馈执行进度,客户端则展示了这一进度和最终结果。

        在以后中,可以在此基础上扩展功能,进一步探索 ROS 的其他特性,比如消息过滤、服务调用等,提升机器人系统的智能和灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

—你的鼬先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值