rospy控制小车多点巡航

该博客介绍了一个使用ROS实现的小车多点巡航控制系统。通过调用/move_base服务,结合位置和角度信息设定目标点,并设置附近约束和超时条件。在巡航过程中,利用控制服务确保高优先级任务可以中断当前巡航。同时,程序实现了对资源的请求和释放,以防止资源抢占问题。
摘要由CSDN通过智能技术生成

rospy控制小车多点巡航

场景:如何实现小车按照规定的路线自主的巡航
这里我采用小车多点导航来实现,且加入附近约束与超时共同作为条件约束。资源服务当出现优先级高于巡航的任务时,中断小车当前的巡航,从而执行新的/move_base任务。

#!/usr/bin/env python
#coding=utf-8
import rospy
import tf
import time
import PyKDL
import actionlib
from nav_msgs.msg import Path
from actionlib_msgs.msg import *
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
from geometry_msgs.msg import PoseWithCovarianceStamped
from tf_conversions import transformations
from math import radians, copysign, sqrt, pow, pi, atan2, cos, sin
from mux.srv import ControlState

class Navigation_multi:
    def __init__(self,robot_name="robot1", wait_time=1800, nearest_r=2):
        self.robot_name = robot_name
        self.move_base = actionlib.SimpleActionClient(str(self.robot_name)+"/move_base", MoveBaseAction)
        self.move_base.wait_for_server(rospy.Duration(60))
        self.nearest_r=nearest_r
        self.wait_time = wait_time
        rospy.on_shutdown(self.shutdown)
    # 四位数转欧拉角
    def quat_to_angle(self,quat):
        rot = PyKDL.Rotation.Quaternion(quat.x, quat.y, quat.z, quat.w)
        return rot.GetRPY()[2]

    # 当前位置
    def get_amcl_pose(self):
        msg = rospy.wait_for_message(str(self.robot_name)+"/amcl_pose",PoseWithCovarianceStamped,timeout=None)
        return msg.pose.pose.position, self.quat_to_angle(msg.pose.pose.orientation)

    # 当前位置到目标位置之间距离
    def stop_pose_distance(self,pose):
        (position, rotation) = self.get_amcl_pose()
        return sqrt(pow((position.x - pose[0]), 2) + pow((position.y - pose[1]), 2))
    
    # 打印启动位置与目标位置
    def print_point(self, pose):
        position = self.get_amcl_pose()[0]
        rospy.loginfo("Start pose: x:%s y:%s    ---------->    Stop pose: x:%s y:%s", position.x, position.y, pose[0], pose[1])

    def _done_cb(self, status, result):
        rospy.loginfo("navigation done! status:%d result:%s"%(status, result))

    def _active_cb(self):
        rospy.loginfo("[Navi] navigation has be actived")

    def _feedback_cb(self, feedback):
        rospy.loginfo("[Navi] navigation feedback\r\n%s"%feedback)

    # 资源的请求与释放 请求返回True False
    def control_client(self, permission, state):
        rospy.wait_for_service(str(self.robot_name)+"/control_server")
      
        try:
            client = rospy.ServiceProxy(str(self.robot_name)+"/control_server", ControlState)
            response = client(permission,state)
            return response.control
        except:
            return False
     
    def shutdown(self):
        # Always stop the robot when shutting down the node.
        self.control_client(1,0)
        rospy.loginfo("Stopping the robot...")
        self.move_base.cancel_goal()
        rospy.sleep(1)

    # 多目标附近巡航
    def go_on_patrol(self, goals):
        for pose in goals:
            goal = MoveBaseGoal()
            goal.target_pose.header.frame_id = 'map'
            goal.target_pose.header.stamp = rospy.Time.now()
            goal.target_pose.pose.position.x = pose[0]
            goal.target_pose.pose.position.y = pose[1]
            q = transformations.quaternion_from_euler(0.0, 0.0, pose[2]/180.0*pi)
            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]

            # 向控制发送 优先级:1 | 请求资源:1(1请求资源,0释放资源)
            if self.control_client(1,1):
                # 休眠两秒等待资源释放
                rospy.sleep(2)
                # 发送打印启动--->目标
                self.print_point(pose)
                self.move_base.send_goal(goal, self._done_cb, self._active_cb, self._feedback_cb)
                # 记录启动时间
                start = time.time()
                # 设定检测频率:检测是否到达目标附近频率、检测是否超时频率、检测是否资源被优先级高抢占频率
                rate = rospy.Rate(1)
                while True:
                    if rospy.is_shutdown():
                        rospy.loginfo("Ros is shutdown!")
                        break
                    elif float(self.stop_pose_distance(pose)) < float(self.nearest_r):
                        rospy.loginfo("The robot reaches the nearest constraint")
                        break
                    elif int(time.time()-start) > int(self.wait_time):
                        rospy.loginfo("Time out")
                        break
                    elif self.control_client(1,1) == False:
                        ros.loginfo("Resource occupied")
                        break
                    rate.sleep()
                # 取消目标请求
                self.move_base.cancel_goal()
                # 释放资源
                self.control_client(1,0)
                rospy.sleep(2)
            else:
                rospy.loginfo("Resource request failed")
                rospy.loginfo("Current location \n <------------> \n %s",pose)
                break
            
if __name__ == "__main__":
    rospy.init_node('Navigation_multi',anonymous=True)
    robot_id = rospy.get_param('~robot_num','3')
    robot_name = 'robot'+ str(robot_id)
    goalListX = rospy.get_param('~goalListX', '2.0, 2.0')
    goalListY = rospy.get_param('~goalListY', '2.0, 4.0')
    goalListYaw = rospy.get_param('~goalListYaw', '0, 90.0')
    goals = [[float(x), float(y), float(yaw)] for (x, y, yaw) in zip(goalListX.split(","),goalListY.split(","),goalListYaw.split(","))]
    navi = Navigation_multi(robot_name=robot_name,wait_time=1800, nearest_r=2)
    navi.go_on_patrol(goals)
    rospy.sleep(1)

总结

通过简单优先级服务,防止资源抢占问题

 介绍如何为机器人整合导航包,实现有效控制和自主导航等功能 目录:  ROS 与 navigation 教程-目录  ROS 与 navigation 教程-设置机器人使用 TF  ROS 与 navigation 教程-基本导航调试指南  ROS 与 navigation 教程-安装和配置导航包  ROS 与 navigation 教程-结合 RVIZ 与导航包  ROS 与 navigation 教程-发布里程计消息  ROS 与 navigation 教程-发布传感器数据  ROS 与 navigation 教程-编写自定义全局路径规划  ROS 与 navigation 教程-stage 仿真  ROS 与 navigation 教程-示例-激光发布(C++)  ROS 与 navigation 教程-示例-里程发布(C++)  ROS 与 navigation 教程-示例-点云发布(C++)  ROS 与 navigation 教程-示例-机器人 TF 设置(C++)  ROS 与 navigation 教程-示例-导航目标设置(C++)  ROS 与 navigation 教程-turtlebot-整合导航包简明指南  ROS 与 navigation 教程-turtlebot-SLAM 地图构建  ROS 与 navigation 教程-turtlebot-现有地图的自主导航  ROS 与 navigation 教程-map_server 介绍  ROS 与 navigation 教程-move_base 介绍  ROS 与 navigation 教程-move_base_msgs 介绍  ROS 与 navigation 教程-fake_localization 介绍  ROS 与 navigation 教程-voel_grid 介绍  ROS 与 navigation 教程-global_planner 介绍  ROS 与 navigation 教程-base_local_planner 介绍2  ROS 与 navigation 教程-carrot_planner 介绍  ROS 与 navigation 教程-teb_local_planner 介绍  ROS 与 navigation 教程-dwa_local_planner(DWA)介绍  ROS 与 navigation 教程-nav_core 介绍  ROS 与 navigation 教程-robot_pose_ekf 介绍  ROS 与 navigation 教程-amcl 介绍  ROS 与 navigation 教程-move_slow_and_clear 介绍  ROS 与 navigation 教程-clear_costmap_recovery 介绍  ROS 与 navigation 教程-rotate_recovery 介绍  ROS 与 navigation 教程-costmap_2d 介绍  ROS 与 navigation 教程-costmap_2d-range_sensor_layer 介绍  ROS 与 navigation 教程-costmap_2d-social_navigation_layers 介绍  ROS 与 navigation 教程-costmap_2d-staticmap 介绍  ROS 与 navigation 教程-costmap_2d-inflation 介绍  ROS 与 navigation 教程-obstacle 层介绍  ROS 与 navigation 教程-Configuring Layered Costmaps
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值