# How to set to a ROS system a fixed communication frequency?

I have a ROS system with 2 nodes. The first node receives a string of data from a raspberry by using serial port and it uploads on in a topic. The second node subscribes to that topic, it gets the data and after some calculations it sends a string to a microcontroller using another serial port. The calculations include some equations that depend on time.

Let's say that I want to send the data to the microcontroller at a fixed frequency (66.67 Hz), but the calculations depend on data from all the system. How can I achieve that from the moment I run all the nodes the system is going to send the data to the microcontroller with this fixed frequency? Do I have to set the whole system under a common time frame? and if that is the case, how can I do it? I think that by setting only the rate to the second node to match that frequency will not solve my problem. After a small research I found that rospy.rostime might be helpful, but I didn't find any example on how to use it and what exactly can offer. I am new to ROS so I still try to find out how things work. I use ROS Kinetic, in Ubuntu 16.04 LTS and my nodes are in Python 2.7.12. Thank you in advance.

UPDATE:

The code running on my Raspberry Pi is:

#!/usr/bin/env python
import random
import decimal
import time
import serial

ser = serial.Serial(

port = '/dev/ttyAMA0',
baudrate = 115200,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)

time.sleep(2)

counter = 0

while 1: # i while True:
x = float(decimal.Decimal(random.randrange(0, 5010))/10)
y = float(decimal.Decimal(random.randrange(0, 5010))/10)
z = float(decimal.Decimal(random.randrange(0, 5010))/10)
thita = float(decimal.Decimal(random.randrange(0, 5010))/10)
u_x = float(decimal.Decimal(random.randrange(0, 5010))/10)
u_y = float(decimal.Decimal(random.randrange(0, 5010))/10)
string_buffer = str(x)+","+str(y)+","+str(z)+','+str(thita)+','+str(u_x)+','+str(u_y)+'/'+'\n'
print string_buffer
ser.write(string_buffer)
time.sleep(1)
counter += 1

ser.close()


and the code of the first node (receiving from Pi and publishing on topic) is:

#!/usr/bin/python

import rospy
import serial
import time
from std_msgs.msg import String

ser = serial.Serial('/dev/ttyS0', 115200)
print (ser.name)
time.sleep(2)

def camera_node():
pub = rospy.Publisher('real_position', String, queue_size=10) # to$rospy.init_node('camera_node', anonymous=True) rate = rospy.Rate(1) #hz, mporei na thelei sygxronismo me ta ypolo$
print("kokos")
if ser.isOpen():
print("in the loop")
camera_str = ser.readline() #... auto p tha diavazei apo serial
#print(camera_str)
pub.publish(camera_str)
rate.sleep()

if __name__ == '__main__':
try:
while not rospy.is_shutdown():
camera_node()
ser.close()
except rospy.ROSInterruptException:
pass

edit retag close merge delete

Sort by » oldest newest most voted

You can achieve what you want here by controlling the rate at which messages are published by the first node, assuming that the time taken by the second to process each messages is relatively constant. The message passing system is fundamentally event based, so only a publisher can set the rate, the subscriber simply runs at the rate messages are received (or slower if they can't be processed fast enough)

You say your first node receives a string from a raspberry pi, does the node have any control over 'when' it receives this string or is it pushed by the hardware? This is important because this is the node which needs to publish at exactly 66.7 Hz, so if it can control when it reads from the Pi it makes it easier to achieve this.

Your second node will then be subscribing to a topic which i published at 66.7 Hz, so it's callback (CPU allowing) will be running at the same rate. This node will then be able to write to the port at the correct frequency, although there will be a phase offset between the original read on node one and the write out on node two.

Hope this makes sense.

more

The only time control I have in the first node is the rate = rospy.Rate() which is set to be equal to the time.sleep() duration in raspberry pi's code loop.

( 2019-01-29 09:43:07 -0500 )edit
1

Can you show us the source code for the first node and the code on the raspberry pi. We can't help you much more unless we see what's actually happening.

( 2019-01-29 11:32:43 -0500 )edit

@PeteBlackerThe3rd I updated my post with the source codes. The rospy.rate is set to 1 only for testing reasons.

( 2019-01-30 04:57:57 -0500 )edit

Is there a reason why you're using a serial port to get the data off the pi? Since a pi is capable of running ROS itself it would seem much easier to network the pi and have a ROS node running on there, this would greatly simplify your system.

( 2019-01-30 06:20:49 -0500 )edit

If I get it correctly, the node running on the RPi will publish the data directly to the topic with the desired frequency. In that case, my first node (as it is now) will be no needed at all. Is this way going to solve my timing problem? Because if it is just an easier way to do the same thing...

( 2019-02-01 12:43:26 -0500 )edit

... as I do now, I don't want to waste time to setup ROS in RPi. Also how these two nodes (1 on RPi and 1 on my pc) are going to communicate under the same ROS system?

( 2019-02-01 12:46:27 -0500 )edit

ROS is a fundamentally distributed system as long as there is a network connection between the computers then nodes on any computer can communicate with any other node.

( 2019-02-01 14:34:19 -0500 )edit