【ros实验三】使用 ROS 动作(Action)机制实现目标请求——实现零件完成度检测(python)

目录

前言

一,创建工作空间(略)

二,创建功能包

三,配置“环境”

(1)在功能包文件夹下创建action文件夹,定义action文件

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

(1)在对应功能包的src下创建python文件(略)

(2)服务端代码

(3)客户端代码

五,运行


前言

action可以简单理解成service的升级版

一般适用于耗时的请求响应场景,以获取连续的状态反馈

                                                                action结构图解

一,创建工作空间(略)

二,创建功能包

catkin_create_pkg task_service roscpp rospy std_msgs actionlib actionlib_msgs

三,配置“环境”

(1)在功能包文件夹下创建action文件夹,定义action文件

action 文件内容组成分为三部分:请求目标值、最终响应结果、连续反馈,三者之间使用---分割示例内容如下:

int32 num
---
int32 result
---
float64 progress_percentage

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

 

四,服务端和客户端代码编写

(1)在对应功能包的src下创建python文件(略)

(2)服务端代码

#!/usr/bin/env python3
import rospy
import actionlib
from task_action.msg import CheckAction, CheckFeedback, CheckResult
# 这里的import可以用*,也可以明确指明导入的具体类型,可读性高

class CheckServer:
    def __init__(self):
        # 初始化一个Action服务器
        # 创建一个SimpleActionServer
        # 参数1: action名字,用于匹配客户端和服务器
        # 参数2: Action类型,定义goal, result, feedback的消息类型
        # 参数3: 回调函数,当接收到一个新的goal时会被调用
        # 参数4: auto_start参数,这里设置为False意味着需要手动调用start()
        self.server = actionlib.SimpleActionServer("part_check", CheckAction, self.cb, False)
        self.server.start()
        rospy.loginfo("服务端启动")

    def cb(self, goal):
        # 总零件数
        total_parts = goal.num
        # 已检测的零件数
        checked_parts = 0

        # 初始化Feedback和Result消息
        feedback = CheckFeedback()
        result = CheckResult()

        rate = rospy.Rate(1)  # 设置频率为每秒执行一次

        # 循环,直到所有零件都被检查
        while checked_parts < total_parts:
            checked_parts += 1
            # 计算并更新进度百分比
            feedback.progress_percentage = (checked_parts / float(total_parts)) * 100.0

            rospy.loginfo("检测 %d 个零件", checked_parts)
            # 向客户端发布进度反馈
            self.server.publish_feedback(feedback)

            rate.sleep()

        # 设置最终的检测结果
        result.result = checked_parts
        self.server.set_succeeded(result)
        rospy.loginfo("检测完成")

if __name__ == "__main__":
    rospy.init_node("task_action_server")
    server = CheckServer()
    rospy.spin()

(3)客户端代码

#!/usr/bin/env python3

import rospy
import actionlib
from task_action.msg import CheckAction, CheckGoal, CheckFeedback

def done_cb(state, result):
    # 当目标完成时的回调
    if state == actionlib.GoalStatus.SUCCEEDED:
        rospy.loginfo("检测完成")

def active_cb():
    # 当目标激活时的回调
    rospy.loginfo("开始检测...")

def fb_cb(feedback):
    # 进度反馈的回调
    rospy.loginfo("%.2f%%", feedback.progress_percentage)

if __name__ == "__main__":
    rospy.init_node("task_action_client")

    # 创建一个Action客户端
    client = actionlib.SimpleActionClient("part_check", CheckAction)

    # 等待服务器准备好
    client.wait_for_server()

    # 设置并发送目标给服务器
    goal = CheckGoal()
    goal.num = 40

    client.send_goal(goal, done_cb, active_cb, fb_cb)

    rospy.spin()

五,运行

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的Python代码示例,用于在ROS实现多点导航: ```python #!/usr/bin/env python import rospy from geometry_msgs.msg import PoseStamped from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal from actionlib import SimpleActionClient from tf.transformations import quaternion_from_euler def movebase_client(x, y, yaw): client = SimpleActionClient('move_base', MoveBaseAction) client.wait_for_server() goal = MoveBaseGoal() goal.target_pose.header.frame_id = "map" goal.target_pose.header.stamp = rospy.Time.now() goal.target_pose.pose.position.x = x goal.target_pose.pose.position.y = y q = quaternion_from_euler(0, 0, yaw) goal.target_pose.pose.orientation.x = q[0] goal.target_pose.pose.orientation.y = q[1] goal.target_pose.pose.orientation.z = q[2] goal.target_pose.pose.orientation.w = q[3] client.send_goal(goal) wait = client.wait_for_result() if not wait: rospy.logerr("Action server not available!") rospy.signal_shutdown("Action server not available!") else: return client.get_result() if __name__ == '__main__': try: rospy.init_node('multi_point_navigation') # 设置导航点列表 points = [(1.0, 2.0, 0.0), (3.0, 4.0, 1.57), (5.0, 6.0, 3.14)] for point in points: result = movebase_client(point[0], point[1], point[2]) if result: rospy.loginfo("Goal execution done!") else: rospy.loginfo("Goal execution failed!") rospy.spin() except rospy.ROSInterruptException: rospy.loginfo("Navigation interrupted!") ``` 上述代码使用move_base的SimpleActionClient来实现多点导航。在`movebase_client`函数中,设置了每个导航点的位置和姿态,并将目标发送给move_base节点。然后,使用`client.wait_for_result()`等待move_base节点返回结果。 在`main`函数中,我们定义了一个包含多个导航点的列表,并用循环逐个调用`movebase_client`函数。最后,我们使用`rospy.spin()`保持节点处于活动状态,并处理ROS回调函数。 注意:在运行此代码之前,确保已正确配置导航栈和move_base节点,并运行ROS导航栈。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值