Search code examples
pythonros

How to move robot forward and backward until the execution is stop in python


There are two question I would like to ask. First, I would like to move the robot forward in 4 seconds and backward in 4 seconds until I stop the program myself. I've run this code to move the robot forward and backward and there is no error. But the robot doesn't move. May I know why and is there anyone can help me with a new coding?

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
import time

rospy.init_node('lastforward')
rate=rospy.Rate(4)
pub=rospy.Publisher('/cmd_vel', Twist, queue_size=1)

move=Twist()
def move_x_secs(secs):
    move.linear.x = 0.4
    time.sleep(secs)
    move.linear.x = 0.0
    time.sleep(secs)
    move.linear.x = -0.4
    time.sleep(secs)
    move.linear.x = 0.0
    time.sleep(secs)
    return

move_x_secs(4)


while not rospy.is_shutdown():
    pub.publish(move)
    rate.sleep()

But when I remove some code just to test the code, the robot can move forward after waiting for 4 seconds and when I aborting the program, the robot keep moving. May I know why?

#! /usr/bin/env python

import rospy
from geometry_msgs.msg import Twist
import time

rospy.init_node('lastforward')
rate=rospy.Rate(4)
pub=rospy.Publisher('/cmd_vel', Twist, queue_size=1)

move=Twist()
def move_x_secs(secs):
    move.linear.x = 0.4
    time.sleep(secs)

move_x_secs(4)

while not rospy.is_shutdown():
    pub.publish(move)
    rate.sleep()

Solution

  • move.linear.x = 0.4 takes only effect from the moment you publish.

    In the first example you only publish the final value. That's why it won't move.

    #! /usr/bin/env python
    
    import rospy
    from geometry_msgs.msg import Twist
    import time
    
    rospy.init_node('lastforward')
    rate=rospy.Rate(4)
    pub=rospy.Publisher('/cmd_vel', Twist, queue_size=1)
    
    move=Twist()
    def move_x_secs(secs):
        # set speed to 0.4 but not yet letting the robot know
        move.linear.x = 0.4
        time.sleep(secs)
    
        # set speed to 0.0 but not yet letting the robot know
        move.linear.x = 0.0
        time.sleep(secs)
    
        # set speed to -0.4 but not yet letting the robot know
        move.linear.x = -0.4
        time.sleep(secs)
    
        # setting speed to 0.0, the final value
        move.linear.x = 0.0
        time.sleep(secs)
        return
    
    move_x_secs(4)
    
    
    while not rospy.is_shutdown():
        # after setting the speed from 0.4 to 0 to -0.4 back to 0, letting the robot know its speed is the final value, 0
        pub.publish(move)
        rate.sleep()
    

    In the second example it indeed will move because 0.4 is the final value.

    #! /usr/bin/env python
    
    import rospy
    from geometry_msgs.msg import Twist
    import time
    
    rospy.init_node('lastforward')
    rate=rospy.Rate(4)
    pub=rospy.Publisher('/cmd_vel', Twist, queue_size=1)
    
    move=Twist()
    def move_x_secs(secs):
        move.linear.x = 0.4
        time.sleep(secs)
    
    move_x_secs(4)
    
    while not rospy.is_shutdown():
        pub.publish(move)
        rate.sleep()
    

    The reason why it first waits for 4 seconds is because you first call the function, where you use time.sleep(4), after that you publish.

    If you want to move your robot 4 seconds forwards and 4 seconds backwards you should try something like the following code.

    #! /usr/bin/env python
    
    import rospy
    from geometry_msgs.msg import Twist
    import time
    
    rospy.init_node('lastforward')
    rate=rospy.Rate(4)
    pub=rospy.Publisher('/cmd_vel', Twist, queue_size=1)
    
    
    while not rospy.is_shutdown():
        move = Twist()
    
        # move forward
        move.linear.x = 0.4
        pub.publish(move)
        rospy.sleep(4)
    
        # move backward
        move.linear.x = -0.4
        pub.publish(move)
        rospy.sleep(4)
    
        
        # stop
        move.linear.x = 0.0
        pub.publish(move)
        rospy.sleep(4)
    

    Note that you should not be use time.sleep() when using the rospy module, instead use rospy.sleep() or rospy.rate().