ROS+python控制小乌龟走方形的实现

本文介绍了使用ROS和Python控制小乌龟行走正方形的方法,通过改进的控制策略提高了行走的精度。虽然原始代码可能受到硬件和线程的影响,导致形状不规则,但采用模仿ROS框架的Python代码能够更好地控制乌龟行动,使得绘制的方形更加整齐。通过调整`rospy.Timer`的时间间隔,可以进一步优化拐角的判断,达到更好的行走效果。
部署运行你感兴趣的模型镜像

常见的简陋的控制乌龟行走方形的方式很简单,例如:

代码有些地方是测试用的,可以不要。

#! /usr/bin/env python

from pickle import TRUE
import rospy
from turtlesim.msg import Pose
from geometry_msgs.msg import Twist
from rospy.timer import Timer


PI=3.141592653
turn=True
twist=Twist()
def subCallback(pose):

    rospy.loginfo("come into subCallback!%f",pose.x)
    

def timeCallback(event):

    pub=rospy.Publisher("turtle1/cmd_vel",Twist,queue_size=1)
    global turn
    if turn:
        twist.linear.x=1
        twist.angular.z=0.0
        turn=False
    else:
        twist.linear.x = 0
        twist.angular.z = 1*PI/2
        turn=TRUE
    pub.publish(twist)

if __name__=="__main__":


    rospy.init_node("go_square")

    sub = rospy.Subscriber("turtle1/pose", Pose, subCallback, queue_size=10)

    rospy.Timer(rospy.Duration(1),timeCallback, oneshot=False)


    rospy.spin()

    
    pass

用rospy.Timer每隔一段固定时间改变乌龟策略,在行进和转弯中进行改变。这样的代码可能受硬件和线程影响较大,画出的方形比较粗糙。如下图:

当然,不用rospy.Timer也可以实现,但总感觉画的不踏实,比较有偶然性。

下边是模仿ROS自带的乌龟走方形的框架,利用Python写的,这样对乌龟的控制比较强,效果比较好。代码如下:

#! /usr/bin/env python

from genpy.message import fill_message_args
import rospy
from turtlesim.msg import Pose
from geometry_msgs.msg import Twist
from rospy.timer import Timer
from math import cos, fabs, sin
from enum import Enum

State=Enum('State',('MOVE','STOP_MOVE','TURN','STOP_TURN'))

now_pose=Pose()
goal_pose=Pose()
g_state=State.MOVE                                                                            
PI = 3.141592653
twist = Twist()
first_set_goal=True





def subCallback(pose):
    
    global now_pose
    now_pose = pose

def control(pub,linear,angular):
    global twist
    twist.linear.x=linear
    twist.angular.z=angular
    pub.publish(twist)

#whether the turtle has reached the goal 
def hasReachedGoal():
    global now_pose, goal_pose
   
    return (fabs(now_pose.theta-goal_pose.theta)<0.001)&(fabs(now_pose.x-goal_pose.x)<0.001)&(fabs(now_pose.y-goal_pose.y)<0.001)

#wheather the turtle has stopped 
def hasStopped():
    global now_pose
    return ((now_pose.linear_velocity<0.001)&(now_pose.angular_velocity<0.001))


def stopMove(pub):
    global goal_pose,g_state,now_pose

    if hasStopped():
        g_state=State.TURN
        goal_pose.x = now_pose.x
        goal_pose.y = now_pose.y
        goal_pose.theta = now_pose.theta+PI/2
        if goal_pose.theta>PI:
            goal_pose.theta=goal_pose.theta-2*PI
    else:
        control(pub,0,0)
    rospy.loginfo('停止行走')


def stopTurn(pub):
    global goal_pose,g_state,now_pose

    if hasStopped():
        g_state=State.MOVE
        goal_pose.x = now_pose.x+cos(now_pose.theta)*2
        goal_pose.y = now_pose.y+sin(now_pose.theta)*2
        goal_pose.theta = now_pose.theta
    else:
        control(pub,0,0)
    rospy.loginfo('停止转弯')


def move(pub):

    global g_state
    if hasReachedGoal():
        g_state=State.STOP_MOVE
        control(pub,0,0)
    else:
        control(pub,1,0)
    rospy.loginfo('直线行走move')


def turn(pub):
    global g_state
    if hasReachedGoal():
        g_state=State.STOP_TURN
        control(pub,0,0)
    else:
        control(pub,0,PI/4)
    rospy.loginfo('转弯')



def timeCallback(event):
    
    rospy.loginfo("come into timeCallback.....")

    pub = rospy.Publisher("turtle1/cmd_vel", Twist, queue_size=1)

    global goal_pose,now_pose, first_set_goal,g_state
    #if this is the first time to call this function
    if first_set_goal:
        goal_pose.x = now_pose.x+cos(now_pose.theta)*2
        goal_pose.y = now_pose.y+sin(now_pose.theta)*2
        goal_pose.theta = now_pose.theta

        first_set_goal=False

    if g_state==State.STOP_MOVE:
        rospy.loginfo('状态为:'+str(g_state))
        stopMove(pub)
    elif g_state==State.MOVE:
        rospy.loginfo('状态为:'+str(g_state))
        move(pub)
    elif g_state==State.TURN:
        turn(pub)
    else:
        stopTurn(pub)

if __name__ == "__main__":

    rospy.init_node("go_square")


    sub = rospy.Subscriber("turtle1/pose", Pose, subCallback,queue_size=10)

    rospy.Timer(rospy.Duration(0.016), timeCallback, oneshot=False)


    rospy.spin()
 


    pass

 运行图如下:

绘制的方形相对比较整齐。但根据计算机当前分配内存和CPU影响,有时可能仍会出现在拐弯处出现过度判断。当然,如果把:

   rospy.Timer(rospy.Duration(0.016), timeCallback, oneshot=False)

中0.016改为更小数字,效果应该会更好。个人感觉应该就向微分那样,分的约细小就能判断更好。不过还未 验证。

 

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值