how to use Twist with Duration()

asked 2019-12-01 20:50:27 -0500

Redhwan gravatar image

updated 2019-12-03 23:09:26 -0500

I'd like to make the robot moves a certain distance toward x-direction using Twist with Duration() without while loop or rospy.get_rostime().to_sec() ,

ex: I'd choose 60 sec like Duration(60) and move_cmd.linear.x = 0.2. it will move the distance = 0.2 * 60 = 12 m

this idea will solve many issues for me which forced with move_base and converted the coordinates with Odometry

this full code:

the robot moves without stops, I'd also add Duration and remove while loop.

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist


class GoForward():
    def __init__(self):
        rospy.init_node('GoForward', anonymous=False)
        rospy.loginfo("To stop TurtleBot CTRL + C")
        rospy.on_shutdown(self.shutdown)
        self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
        r = rospy.Rate(50)
        move_cmd = Twist()
        move_cmd.linear.x = 0.2
        move_cmd.angular.z = 0
        while not rospy.is_shutdown():
            self.cmd_vel.publish(move_cmd)
            r.sleep()

    def shutdown(self):
        rospy.loginfo("Stop TurtleBot")
        self.cmd_vel.publish(Twist())
        rospy.sleep(1)


if __name__ == '__main__':
    try:
        GoForward()
    except:
        rospy.loginfo("GoForward node terminated.")

I spent more time on it, it seems easy but it is difficult for me.

please help me or any suggestions.

Edit:

I tried with Timer but it didn't work with me, it ran without continue. It seems to while loop or starts time.

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
class GoForward():
    def __init__(self):
        rospy.init_node('GoForward', anonymous=False)
        rospy.on_shutdown(self.shutdown)
        self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
        rospy.Timer(rospy.Duration(2), self.my_callback)
    def my_callback(self, event):
        move_cmd = Twist()
        move_cmd.linear.x = 0.2
        move_cmd.angular.z = 0
        self.cmd_vel.publish(move_cmd)
    def shutdown(self):
        rospy.loginfo("Stop TurtleBot")
        self.cmd_vel.publish(Twist())
        rospy.sleep(1)
if __name__ == '__main__':
    try:
        GoForward()
    except:
        rospy.loginfo("GoForward node terminated.")
edit retag flag offensive close merge delete

Comments

Could you please explain where in this your actual problem is? What have you tried, what didn't work and what did you expect vs. what did you actually see?

Also, please note that this approach sounds nice in theory, but due to wheel slip, timing issues, acceleration/deceleration, and many more factors, you'll (almost) never end up with the expected distance...

Also, I'm not quite sure if this isn't an xy-problem. Could you explain a little bit what your use case is and why this doesn't work e.g. with move_base?

mgruhler gravatar image mgruhler  ( 2019-12-02 01:33:49 -0500 )edit

my issue in this my previous question, it wrote before few days here . how to stop this line move_cmd.linear.x = 0.2 after 60 sec? second thing when using rospy.get_rostime().to_sec() which need to add while loop lead to freeze the video,

Redhwan gravatar image Redhwan  ( 2019-12-02 05:31:41 -0500 )edit

I'm not sure I understand you correctly... What about a while loop and a video? There is neither some kind of video mentioned here nor in the other question you link to...

I still don't think that this is the way you should proceed, but to answer your question about stopping the publishing of the velocity, why not try something like this:

start = rospy.Time.now()
timeout = rospy.Duration(60)
while not rospy.is_shutdown():
    if rospy.Time.now - start > timeout:
        # you might want to publish a zero here, or break out of the while loop or however you want to handle when the 60 s passed...
        pass
    else:
        self.cmd_vel.publish(move_cmd)
    r.sleep()
mgruhler gravatar image mgruhler  ( 2019-12-02 06:35:12 -0500 )edit

First of all, thank you a lot for your help.

sorry, I have a long code but I use a part of it here, I mentioned there 'the human following with OpenCV '.

while loop changes in a number of the frame per second if it used, as a result, the video freezes. So, I wonder if there is any method to solve the issue smoothly, similar this it used success = self.move_base.wait_for_result(rospy.Duration(60)) with move_base because I have the velocity is a known. theoretically, we can calculate the distance if using a Duration(xxxx).

my background is good with ROS but not enough.

I think while loop is the simplest way but with OpenCV is bad. second thing use Odometry like these codes here , here. I already used Odometry b

Redhwan gravatar image Redhwan  ( 2019-12-02 07:40:24 -0500 )edit

I already used Odometry but when the robot moves a long time, it becomes inaccurate. So, I post this question here.

Redhwan gravatar image Redhwan  ( 2019-12-02 07:45:52 -0500 )edit

One workaround would be using a separate thread or a ros timer. You can publish the twist within the timer callback, update the time and handle the publishing logic there.

pavel92 gravatar image pavel92  ( 2019-12-03 02:56:01 -0500 )edit

@pavel92 thank you for your help. I tried to implement it with Timer but failure. So, I edited my question and added the code.

could you help me

Redhwan gravatar image Redhwan  ( 2019-12-03 23:12:05 -0500 )edit

I don't fully understand "ran without continue. It seems to while loop or starts time." Does it run once and stop? You need something to keep the node alive, e.g., a while not rospy.is_shutdown() loop or rospy.spin(); otherwise, the node will finish before the timer triggers the callback. Also, for troubleshooting, I would shorten the duration and use logging or a print statement to test the callback functionality before issuing velocity commands.

tryan gravatar image tryan  ( 2020-01-21 08:30:46 -0500 )edit