0
$\begingroup$

Rosanswers logo

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

Originally posted by murali1842 on ROS Answers with karma: 23 on 2018-11-26

Post score: 0


Original comments

Comment by jayess on 2018-11-27:
Just so you know, your rospy.Rate object is not operating at 10Hz, it's operating at 0.5Hz.

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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.


Originally posted by PeteBlackerThe3rd with karma: 9529 on 2018-11-27

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by murali1842 on 2018-11-27:
Could you share some link with the above-mentioned description?

Comment by PeteBlackerThe3rd on 2018-11-27:
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.

Comment by murali1842 on 2018-11-27:
Thanks @PeteBlackerThe3rd. Let me try and see.

Comment by murali1842 on 2018-11-27:
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???

Comment by PeteBlackerThe3rd on 2018-11-27:
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.

Comment by PeteBlackerThe3rd on 2018-11-27:
I've moved your new code into your original question and given you the updates you need to make this work now.

Comment by murali1842 on 2018-11-27:
I need continuous publishing, when i need if self.on==True, i am getting only one time.

Comment by PeteBlackerThe3rd on 2018-11-27:
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.

Comment by murali1842 on 2018-11-27:
perfecto... I got it. IT is working. thanks a lot

Comment by murali1842 on 2018-12-03:
Hey commands in python similar to rospy.Timer(duration , command)? @PeteBlackerThe3rd

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.