Publish when Subscribers have finished their loop.

asked 2019-10-04 08:00:02 -0500

mhyde64 gravatar image

I have a ros build that is working quite well. I take a DataFrame of coordinates (x, y, z) and covert them, one at a time, to a list of 4 angles. That list is then published to a single topic and 4 subscriber nodes each take their respective angle from that list. Once the subscribers receive their angles they call a function to move a motor to that angle.

The issue that I'm having (less of an issue and more of a desire) is that I would like the 4 nodes to tell the publisher when they are done and once all four say they are done then the publisher will send the next set of angles. Otherwise I have to allow for the longest possible rotation time even if the operation will take a fraction of that.

I have looked into both services and a publisher/subscriber in one system and can't seem to find a reasonable solution.

I have attached a copy of my publisher and one of my subscribers. Any suggestions?

PUBLISHER:

def motorMaster():
'''
The Master Node defined as a function. Using a multiarray message, the 4 angles are calculated
by the functions brought in from motorControls and then published to a single topic. Each motor
pulls its respective command from that multiarray.
'''
angPub = Publisher('motAngs', Float32MultiArray, queue_size=10)
init_node('master', anonymous=True)
rate = Rate(.5)
while not is_shutdown():
    for i in dataFrame.values:
        angles = genAngles(list(i))
        loginfo(angles)
        angPub.publish(data=angles)
        rate.sleep()
if __name__ == '__main__':
    try:
        motorMaster()
    except ROSInterruptException:
        pass

SUBSCRIBER:

def baseAngCall(data):
'''
Logs the angle calculated by the master and feeds it to the base motor.
'''
loginfo(data.data[0])
baseAng = data.data[0]
baseMotor.moveToAngle(baseAng)

def baseMotNode():
    '''
    Subscriber Node for the base motor.
    '''
    init_node('baseMotor', anonymous=True)
    Subscriber('motAngs', Float32MultiArray, baseAngCall)
    spin()

if __name__ == '__main__':
    gpioInit(11, 12)
    baseMotNode()

NOTE: Many of the functions used are hosted in another python file used as a module to keep the nodes clean.

edit retag flag offensive close merge delete

Comments

1

I have looked into both services and a publisher/subscriber in one system and can't seem to find a reasonable solution.

What went wrong exactly ?

Have you tried to make your subscribers publish on a topic like /finished that the original publisher could subscribe too ?

Have you considered using an action server ?

Delb gravatar image Delb  ( 2019-10-04 09:57:43 -0500 )edit

"Have you tried to make your subscribers publish on a topic like /finished that the original publisher could subscribe too ?"

That seems to be the solution. I think I was overthinking it and under the assumption the publish data has to occur in a loop, which isn't necessarily true. I could do something have the motor nodes receive the angle. Then, after the motor counts through its steps, the node will publish 1 a single time. When the master receives 4 1s (adds them to 4) that will trigger the next coordinate. Do you think something like that would work? It's tough because I'm running this build on a raspberry pi at my house and I am working on it remotely so I'll add a bunch of changes with no way to test them (my own impatience).

I am brand new to ROS so forgive me ...(more)

mhyde64 gravatar image mhyde64  ( 2019-10-04 10:23:27 -0500 )edit

I found a solution.

Since my motors will all move at the RPM that will provide max torque and all of my angles are determined in the master what I can do is calculate the sleep time based on the largest angle being sent.

mhyde64 gravatar image mhyde64  ( 2019-10-04 14:20:54 -0500 )edit
1

what I can do is calculate the sleep time based on the largest angle being sent

Are you saying that you'll simply wait some time before sending the next angles ? That could work but it's not recommended. The problem with this method is that it's independant of what the motors will actually do so if, for any reasons, your motors move faster than expected you won't get the desired position before sending the new angles. Your previous comment would be a better approach.

Delb gravatar image Delb  ( 2019-10-07 02:26:17 -0500 )edit

Yes that is correct and you are right that it is problematic. It is working as a temporary fix for now while I work out other features. If anyone still has suggestions about how to set up a finished topic I am all ears.

mhyde64 gravatar image mhyde64  ( 2019-10-07 07:07:40 -0500 )edit