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

Revision history [back]

click to hide/show revision 1
initial version

As mentioned by @janindu, you can use threads to accomplish this task. At the same time, it is possible for you to restructure your code to accomplish the same task as well.

Let's try to understand your task:

When node1 publishes "Start Sanitizing the Room", count_node should start counting from 0 to 100 at a predefined rate. count_node should therefore start counting when it receives the std_msgs String data "Start Sanitizing the Room", and should stop counting when it receives the std_msgs String data "Stop Sanitizing the Room". The count can be seen from a rospy.loginfo statement or from the topic 'progress' that it is publishing to.

#!/usr/bin/env python
import rospy
from std_msgs.msg import String, Int32

keepCounting = True
count = 0

def callback(data):
    global keepCounting, count # global keyword allows us to access global variables
    if (data.data == "Start Sanitizing the Room"): 
        keepCounting = True
    elif (data.data == "Stop Sanitizing the Room"): 
        keepCounting = False

        # Restart the count
        count = 0
    else: 
        # There are 5 logger levels, debug, info, warn, error, and fatal
        rospy.logwarn("Received the wrong data, please check")

def listener(): 
    global keepCounting, count # global keyword allows us to access global variables

    # Start a subscriber to subscribe to String type data and pass the data to the callback function
     rospy.Subscriber('brwsrButtons', String, callback)

    # There are 5 logger levels, debug, info, warn, error, and fatal
     rospy.loginfo("Started listener method")

    # Run this node at 10hz 
     r = rospy.Rate(10)

    # As long as the node is not shutdown keep running this while loop
    while not rospy.is_shutdown():
    if (count < 101 and keepCounting): 
         rospy.loginfo("The count is: " + str(count))
         pub.publish(count)
         count += 1
     r.sleep()

if__name__ == '__main__': 
    # Take note that if anonymous is set to True, the name of the node will be randomised 
    # Something like /countageHandler_13506_1624779538099
    rospy.init_node('countageHandler', anonymous=True)

    # Start a publisher to publish Int32 type data which buffers up to 10 pieces of the data
     pub = rospy.Publisher('progress', Int32, queue_size=10)

    # Call the listener function defined above
    listener()

The reason this works is because you have 2 processes that are running: 1. The while loop in listener 2. The callback function based on the subscriber

As you initially intended in your original code, the count is incremented at a rate of 10hz, once the cleaning stops, the keepCount flag is set to False, and the count is reset to 0. When cleaning starts again, the keepCount flag is set to True and both the cleaning and the count resumes. keepCount flag is a global variable because it is defined outside any of the functions at the top of the code. It can be accessed within each of the functions because of the "global" keyword. Hope this helps!

As mentioned by @janindu, you can use threads to accomplish this task. At the same time, it is possible for you to restructure your code to accomplish the same task as well.

Let's try to understand your task:

When node1 publishes "Start Sanitizing the Room", count_node should start counting from 0 to 100 at a predefined rate. count_node should therefore start counting when it receives the std_msgs String data "Start Sanitizing the Room", and should stop counting when it receives the std_msgs String data "Stop Sanitizing the Room". The count can be seen from a rospy.loginfo statement or from the topic 'progress' that it is publishing to.

#!/usr/bin/env python
import rospy
from std_msgs.msg import String, Int32

keepCounting = True
count = 0

def callback(data):
    global keepCounting, count # global keyword allows us to access global variables
    if (data.data == "Start Sanitizing the Room"): 
        keepCounting = True
    elif (data.data == "Stop Sanitizing the Room"): 
        keepCounting = False

        # Restart the count
        count = 0
    else: 
        # There are 5 logger levels, debug, info, warn, error, and fatal
        rospy.logwarn("Received the wrong data, please check")

def listener(): 
    global keepCounting, count # global keyword allows us to access global variables

    # Start a subscriber to subscribe to String type data and pass the data to the callback function
     rospy.Subscriber('brwsrButtons', String, callback)

    # There are 5 logger levels, debug, info, warn, error, and fatal
     rospy.loginfo("Started listener method")

    # Run this node at 10hz 
     r = rospy.Rate(10)

    # As long as the node is not shutdown keep running this while loop
    while not rospy.is_shutdown():
     if (count < 101 and keepCounting): 
          rospy.loginfo("The count is: " + str(count))
          pub.publish(count)
          count += 1
      r.sleep()

if__name__ == '__main__': 
    # Take note that if anonymous is set to True, the name of the node will be randomised 
    # Something like /countageHandler_13506_1624779538099
    rospy.init_node('countageHandler', anonymous=True)

    # Start a publisher to publish Int32 type data which buffers up to 10 pieces of the data
     pub = rospy.Publisher('progress', Int32, queue_size=10)

    # Call the listener function defined above
    listener()

The reason this works is because you have 2 processes that are running: 1. The while loop in listener 2. The callback function based on the subscriber

As you initially intended in your original code, the count is incremented at a rate of 10hz, once the cleaning stops, the keepCount flag is set to False, and the count is reset to 0. When cleaning starts again, the keepCount flag is set to True and both the cleaning and the count resumes. keepCount flag is a global variable because it is defined outside any of the functions at the top of the code. It can be accessed within each of the functions because of the "global" keyword. Hope this helps! helps!