ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

python ros callback with if-condition timer

asked 2020-07-15 20:24:16 -0500

sneakycoder gravatar image

updated 2020-07-15 20:28:21 -0500

I have a call back set up to receive a string. that string can be 2 different things. Im trying to figure out how i can set up a timer that gets set each time each individual string possibility is recieved. and if that specific string has not been received for more than X seconds, set some flag for current status to false. What i have does not seem to work sense the timer wont persist through the if statement. however if i declare it as timer_a = None before hand , it breaks the timeout calculation.

 def string_cb(string):
   if string == 'A':
      timer_a = rospy.Time.now()
   if string == 'B':
      timer_b = rospy.Time.now()

   timeout_a = (rospy.Time.now() - timer_a).to_sec()
   timeout_b = (rospy.Time.now() - timer_b).to_sec()
   if timeout_a > 5.0:
      A_current = false
   if timeout_b > 5.0:
      B_current = false
edit retag flag offensive close merge delete

Comments

you can make timers global, or make your node class based and add them as class attributes

Choco93 gravatar image Choco93  ( 2020-07-16 01:55:07 -0500 )edit

1 Answer

Sort by » oldest newest most voted
0

answered 2020-07-27 08:46:32 -0500

Bernat Gaston gravatar image

In my opinion, it is better to implement timers with threads. In your case I would have a class that implements a function that simply waits some time and that can be stopped. If it arrives to the timeout, it turns your variable to False. If you receive a new string, you stop the thread and start it again.

Something like this

@staticmethod
def watch_until_string_a(max_time_stopped, stop):
    old_time = rospy.Time.now().to_sec()
    diff_time = 0

    while diff_time < max_time_stopped and not stop():
        time.sleep(0.2)
        diff_time = rospy.Time.now().to_sec() - old_time

    if not stop():
        self.a_current = False

then you can start a timer just by doing

    th = threading.Thread(target=self.watch_until, args=(time_before, lambda: stop[0]))
    th.start()

with stop being a list of a single boolean

   stop = [False]

If you want to stop your thread, you just have to change the value of stop to

   stop = [True]

and you thread will stop without changing the value of the variable. Then just wait for them to finish

   th.join()

and you can launch it again.

The code above is for a single string, but you can easily modify it to be used with the two strings (remember that you will need one thread per string). I hope it helps.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2020-07-15 20:24:16 -0500

Seen: 964 times

Last updated: Jul 27 '20