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

Get tf transform AFTER publishing node has died

asked 2019-07-10 10:19:47 -0500

ROSinenbroetchen gravatar image

updated 2019-07-16 08:24:59 -0500

see original version below

Hey there, I still struggle to get tf transforms out of ros for successive runs of a pygmooptimization problem. At least it does not crash anymore but I have not found a working way to reset/restart the tf listener and buffer yet.

This is what I do for starting the algorithm:

#!/usr/bin/env python

import pygmo as pg
import rospy
import roslaunch
import tf2_ros
import [algo] as co
import sys
from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument("-f", "--bagfile", dest="bagfile",
                    help="write report to FILE", metavar="FILE")
args = parser.parse_args()

# start roscore
uuid_roscore = roslaunch.rlutil.get_or_generate_uuid(None, False)
roscore = roslaunch.parent.ROSLaunchParent(uuid_roscore, [],is_core=True)

# start tf listener
node_name = '[node_name]'
rate = rospy.Rate(10.0)

algo = pg.algorithm(pg.nsga2(gen=100))
problem = pg.problem(co.optimize(args.bagfile))
pop = pg.population(problem, 20)
pop = algo.evolve(pop)

The important part of the class for the evaluation is:

class ProcessListener(roslaunch.pmon.ProcessListener):
process_finished = False
def process_died(self, name, exit_code):
    self.process_finished = True
    rospy.logwarn("%s died with code %s", name, exit_code)
    # global process_finished

class optimize(object):
def __init__(self, bagfile):
    self.bagfile = bagfile
def evaluate(self):
    # start tf listener
    tf_buffer = tf2_ros.Buffer()
    tf2_listener = tf2_ros.TransformListener(tf_buffer)

    # start launchfile
    uuid_launchfile = roslaunch.rlutil.get_or_generate_uuid(None, False)

    cli_args = ['[package_name]', 'launchfile.launch', 'configuration_directory:=$(find [package_name])/config','configuration_basenames:=config.lua', 'bag_filenames:='+self.bagfile]
    roslaunch_args = cli_args[2:]
    roslaunch_file = [(roslaunch.rlutil.resolve_launch_arguments(cli_args)[0], roslaunch_args)]
    process_listener = ProcessListener()
    launchfile = roslaunch.parent.ROSLaunchParent(uuid_launchfile, roslaunch_file, process_listeners=[process_listener],is_core=False)

    #get transform
    transform_received = False

    while not process_listener.process_finished:
        # continue
    print("Process had finished")
    for i in range(3000): 
        if  not transform_received:
                trans = tf_buffer.lookup_transform('map',
                transform_received = True
                print("Transform received")
                # continue
    if(not transform_received):
        print("NO transform received")
        pos_x = 1337.0
        pos_y = 1337.0
        pos_z = 1337.0
        pos_x = trans.transform.translation.x
        pos_y = trans.transform.translation.y
        pos_z = trans.transform.translation.z


    del tf_buffer
    del tf2_listener

    return [pos_x, pos_y, pos_z]

The error message I get is (at the moment, different other tries in the comments e.g. restarting the master...)

Warning: TF_OLD_DATA ignoring data from the past for frame odom at time 1.56268e+09 according to authority /[node]

Possible reasons are listed at
     at line 277 in /tmp/binarydeb/ros-melodic-tf2-0.6.5/src/buffer_core.cpp

How can I manage that each loop iteration starts with fresh (=empty) tf data? As you probably noticed, I am quite new to python.

Hey there,

in order to evaluate the performance of some algorithms, I want to compare the position of my robot after a rosbag with sensor data has finished with another run with different parameters.

The straightforward approach with a TransformListenerdoes not work as the nodes are not sending anymore.

Is there a more convenient solution ... (more)

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted

answered 2019-07-10 11:35:37 -0500

gvdhoorn gravatar image

updated 2019-07-18 03:04:23 -0500

Just a question at this point: if your Listener has been listening while everything was running, it should still have all the transforms. If you then ask for "the latest" transform (ie: ros::Time(0)) it should still be able to answer your query.

Does that not work for you? Are you using ros::Time::now()?

Edit: you might also want to look into the length of the cache for the Listener that you've created. Default is 1 minute I believe. Older TFs will be pruned, and in that case even asking for ros::Time(0) wouldn't work (as the cache would be empty).

Edit 2: I don't know about the rest of your code (I'm not sure I would've chosen your approach as it seems to be doing some things I'm not sure are supposed to be even supported in a single process), but I do notice this:

tf_buffer = tf2_ros.Buffer()

You appear to be using the default length for the Buffer (ie: 10 seconds). I cannot deduce whether that is sufficient for your particular use of these APIs. You may want to consider configuring a larger length using the cache_time argument.

The following should create a Buffer with length 60 seconds:

tf_buffer = tf2_ros.Buffer(cache_time=rospy.Duration(60.0))

It might also be valuable to see which frames are actually known to the tf_buffer object by calling the all_frames_as_string() method on it.

edit flag offensive delete link more


Thank you for your response. Actually, that could work for me. I'll try it.

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-11 02:05:48 -0500 )edit

Still did not manage to fix it. I am using a python script to iterate through the paremeters given by a genetic algorithm. Each time, the master is shut down and a new one is started. In the second loop, I alwasy get an error message saying: rospy.service.ServiceException: service [/[node_name]/tf2_frames] already registered, although I started a new master and tried to unsubscribe before shutting the old one down:

m = rosgraph.masterapi.Master(rospy.get_name())
node_uri = m.lookupNode(node_name)
print("Unregister: " + node_uri + node_name + '/tf2_frames')
m.unregisterService('~tf2_frames',node_uri + node_name + '/tf2_frames')

What am I missing?

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-15 06:01:21 -0500 )edit

rospy.signal_shutdown('Quit') seemed to help. I keep watching.

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-15 06:16:30 -0500 )edit

Each time, the master is shut down and a new one is started

but your nodes aren't?

I'm not entirely sure what you're doing, or whether it's actually connected to your issues, but interacting with the master on a side channel to (de)register services/topics/nodes is probably not entirely sanitary and could introduce some weird effects.

Still did not manage to fix it.

you haven't actually described what doesn't work for you.

If a TfListener has a sufficiently long buffer and it has seen the TFs that you're interested in it should be able to return "the latest" transform to you. Regardless of whether other nodes are still running. It's decoupled from that.

But your last few comments seem to indicate that you're doing some unconventional meddling with the master/your nodes, which could be affecting normal operations.

gvdhoorn gravatar image gvdhoorn  ( 2019-07-15 06:18:01 -0500 )edit

Actually they did. It could be similar to this bug:

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-15 06:19:40 -0500 )edit

It did NOT help. The second iteration, no new ros node is started. Next guess was to start the whole ROS stuff before this iteration loop and to pass the tf2 buffer as parameter. Did not work either.

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-16 07:02:39 -0500 )edit

I'm not sure where the need for capitals comes from.

You still haven't shown me any errors or code of something that doesn't work. Please show actual errors copy-pasted and/or code snippets.

I would still expect lookups to work for frames that were last broadcast N seconds ago if:

  1. the listener has a long enough buffer (at least as long as N, but probably more)
  2. you ask for either a point t that falls before the last broadcast of the frame or ask for "the latest"

Whether or not there still are broadcasters for those frames should not matter.

gvdhoorn gravatar image gvdhoorn  ( 2019-07-16 07:39:56 -0500 )edit

That was just meant as emphasis. I will rewrite the original question with code snippets. The problem is rather that I cannot get rid of the listener and transforms of the preceeding loop run. Even when I shut everything down, including the code. That does not make any sense at all for me.

ROSinenbroetchen gravatar image ROSinenbroetchen  ( 2019-07-16 07:45:27 -0500 )edit

Question Tools


Asked: 2019-07-10 10:19:47 -0500

Seen: 614 times

Last updated: Jul 18 '19