Ask Your Question
0

How to run a ros publisher without a while loop?

asked 2018-11-26 17:09:59 -0500

murali1842 gravatar image

updated 2018-11-27 18:55:48 -0500

jayess gravatar image

I am writing tkinter python program for turning on and off the publisher. I need to turn on and off the publisher using a button. If am writing using while loop, the entire gui freezes, I am unable to operate anything. Please give me some suggestions.

dummy = Button(master, text="dummy", relief='groove', command=self.pub_values)
def pub_values(self):
    self.pub = rospy.Publisher('/gateway', Int32MultiArray, queue_size=10)
    rospy.init_node('talker_int', anonymous=True)
    rate = rospy.Rate(1)  # 10hz
    self.var = Int32MultiArray()
    self.var.data = []
    ls = self.extract_values()
    self.var.data = ls
    self.on = True
    while self.on == True:
        rospy.loginfo(self.var)
        self.pub.publish(self.var)
        rate.sleep()

UPDATE: New code after feedback

import rospy, numpy, threading, time
from std_msgs.msg import Int32MultiArray


if __name__ == '__main__':
    x = Simulat()
    try:
        x.t.start()
    except rospy.ROSInterruptException:
        pass

I need to stop or cancel and restart the above program from console. @PeteBlackerThe3rd

Update 2:

Final working code after suggestions

import rospy, numpy, threading, time 
from std_msgs.msg import Int32MultiArray


class Simulat:
    def __init__(self):
        rospy.init_node('talker_int', anonymous=True)        
        self.pub = rospy.Publisher('/gateway', Int32MultiArray, queue_size=10)
        self.rate = rospy.Rate(0.5)  # 10hz
        self.var = Int32MultiArray()
        self.var.data = []
        self.t = threading.Timer(2.0, self.talker_int)
        self.on = True

    def talker_int(self):
        rate = rospy.Rate(1) # 10hz
        var = Int32MultiArray()
        var.data = []
        ls = range(6000, 6041)
        #while not rospy.is_shutdown():
        while self.on == True:
            k = [x+1 for x in ls]
            var.data = k   #% rospy.get_time()
            rospy.loginfo(var)
            self.pub.publish(var)
            rate.sleep()
            ls = k

if __name__ == '__main__':
    x = Simulat()
    try:
        t = rospy.Timer(rospy.Duration(2), x.talker_int)
    except rospy.ROSInterruptException:
       pass
edit retag flag offensive close merge delete

Comments

Just so you know, your rospy.Rate object is not operating at 10Hz, it's operating at 0.5Hz.

jayess gravatar image jayess  ( 2018-11-27 18:59:06 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2018-11-27 06:30:23 -0500

updated 2018-11-27 12:56:05 -0500

You're approaching event based programming from the wrong angle.

If you want to repeatedly publish a message on a topic sometimes, and control it using a button then you'll need a timer. The architecture should look something like this.

  1. The initialisation of your program should create the publisher object, a timer object and your button. You will also need a global boolean variable which will control the publishing.

  2. The tick callback for your timer object should check the global boolean and publish a single message if it's true.

  3. The button pressed callback should invert the value of the global boolean.

The timer object is used to do the job of the while loop in this case. Hope this gets you going in the right direction.

UPDATE:

Thanks for posting you new code. It's getting closer but there are things you need to fix.

1) You don't need any rate objects for this, so get rid of all of them. The publish rate is set by the timer using this method so rate objects are not needed.

2) There shouldn't be a while loops also, we're getting rid of them. Replace the while statement with an if as shown below:

if self.on == True:

Now if your button is controlling the value of self.on then this should start working.

edit flag offensive delete link more

Comments

Could you share some link with the above-mentioned description?

murali1842 gravatar image murali1842  ( 2018-11-27 08:42:03 -0500 )edit

Sorry there is no page describing this, it's just my high level description of what you need to program to make this work. If you want to build this up in parts try and use a timer object to publish a message constantly. When that's working you can move on.

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-11-27 11:33:16 -0500 )edit

Thanks @PeteBlackerThe3rd. Let me try and see.

murali1842 gravatar image murali1842  ( 2018-11-27 11:36:51 -0500 )edit

I tried it worked. t = threading.Timer(1.0, self.pub_values) when self.on == True it is stopping when i make self.on=False. I want it to restart when i make self.on= True.. any suggestions???

murali1842 gravatar image murali1842  ( 2018-11-27 11:59:09 -0500 )edit

Can you post an update to your original question with your current code, then I'll have a look and see what we can do.

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-11-27 12:20:57 -0500 )edit

I've moved your new code into your original question and given you the updates you need to make this work now.

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-11-27 12:56:39 -0500 )edit

I need continuous publishing, when i need if self.on==True, i am getting only one time.

murali1842 gravatar image murali1842  ( 2018-11-27 13:11:41 -0500 )edit

You need to use the rospy time instead of the threading one, which is a one shot timer. So your code should be: rospy.Timer(2.0, self.talker_int) This will execute the callback and publish a message once every two seconds.

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-11-27 13:37:55 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2018-11-26 17:09:59 -0500

Seen: 884 times

Last updated: Nov 27 '18