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

How do I average 60 values published values from a node

asked 2017-05-15 17:16:27 -0500

SupermanPrime01 gravatar image


Is there a way I can take 60 values from a topic and calculate the average after every 60 values. I'm working with GPS and the accuracy is about 3 meters. So I'll get readings that are ~3 meters of where I'm actually at. Taking the average helps pin point my approximate location but I don't know a way to do it without copying and pasting my data into an excel sheet.

Thank you in advance.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted

answered 2017-05-15 19:39:42 -0500

Geoff gravatar image

The simplest way is to calculate a moving average. Here is some rather ugly code that calculates the average of the 60 most recent numbers received on a topic:

import rospy
from std_msgs.msg import Int32

history = []

def callback(msg):
    global history
    if len(history) > 60:
        history = history[-60:]
    average = sum(history) / float(len(history))
    rospy.loginfo('Average of most recent {} samples: {}'.format(len(history), average))

n = rospy.init_node('moving_average')
s = rospy.Subscriber('/numbers', Int32, callback)

It's averaging integers but modifying it to average GPS values would be simple. Also note that it will immediately start producing an answer even before it gets 60 values. If you don't want that, then you should change it to not calculate an average unless the history length is 60.

This code uses pure Python so it's not that fast. You can do it faster using numpy, for which Stack Overflow is full of answers.

If you explicitly want to take only the last 60 samples, average them, and then wait for 60 more samples before producing another average, then you should only calculate an average if the history length is 60, and clear the history after calculating the average.

A better way to estimate robot pose than a simple moving average is to use a filter such as an Extended Kalman Filter. These are much more involved to write and use, but fortunately you're using ROS and ROS has packages to do this sort of thing for you! The robot_pose_ekf package is one of the most commonly used. It's intended to work with data from sensors such as odometry and IMUs, but it can be convinced to use GPS data. If you have other input data such as odometry then so much the better, because you will get a better position estimate.

edit flag offensive delete link more


Extending this: there is also the robot_localization package which is intended to use GPS data...

mgruhler gravatar image mgruhler  ( 2017-05-16 01:57:52 -0500 )edit

Beware that this solution assumes that the rate of receiving the data is constant which is not always the case. It can lead to errors. Usually it makes more sense to keep values for a certain amount of time rather than a number of values.

VictorLamoine gravatar image VictorLamoine  ( 2021-01-15 03:33:39 -0500 )edit

answered 2021-01-15 03:31:45 -0500

VictorLamoine gravatar image

updated 2021-01-15 03:35:38 -0500

I made a package for this:

It only works for simple topic types.

Values are kept for a certain period of time, this means that the number of values used to compute the moving average varies depending on the publishing rate. (if you are looking for a queue with x elements, this package is NOT what you are looking for)

edit flag offensive delete link more

Question Tools



Asked: 2017-05-15 17:16:27 -0500

Seen: 1,844 times

Last updated: Jan 15 '21