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

How does the clock work in rostest

asked 2021-06-07 00:44:44 -0500

FantasticMrFox gravatar image

I have built a very simple test, something like:

#include <ros/node_handle.h>
#include <gtest/gtest.h>

struct SimpleTicker {

    SimpleTicker(ros::NodeHandle &nh) : _nh(nh) {
       _stateTickTimer = _nh.createTimer(ros::Duration(0.25f),
      &SimpleTicker::incrementVal, this, false, true);
    }

    void incrementVal(const ros::TimerEvent&) {
        val++;
    }

    int val = 0;
    ros::Timer _stateTickTimer;
    ros::NodeHandle _nh;

};


TEST(SlamManagerTest, run_simple_tick) {
    ros::NodeHandle nh(~);
    SimpleTicker s(nh);
    ros::Duration{1}.sleep();
    ASSERT_GT(s.val, 0);
}


int main(int argc, char **argv) 
{
    testing::InitGoogleTest(&argc, argv);
    ros::init(argc, argv, "simple_timer_test");
    ros::NodeHandle nh;
    if (ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, 
                                       ros::console::levels::Debug))
    {
        ros::console::notifyLoggerLevelsChanged(); // show debug output in tests
    }
    return RUN_ALL_TESTS();
}

This extremely simple test, starts a class with a timer that should call back to increment a value every 0.25 seconds. I launch this with the test file:

<launch>
  <test test-name="simple_timer_test" pkg="manager" type="simple_timer_test">
  </test>
</launch>

But the test fails and the value is never incremented. I suspect something is wrong with how I setup rostest to use the clock. Any ideas about this?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2021-06-07 01:11:55 -0500

FantasticMrFox gravatar image

So it looks like the system is not spinning. I guess because of this specific way of running rostest the node, never calls to ros::spin() because it is busy running the tests. So wherever a sleep needs to occur, we need to spin instead, something like this:

template <typename F>
void spin_sleep(ros::Duration duration, F break_condition) {
    auto end = ros::Time::now() + duration;
    while (end > ros::Time::now() && !break_condition()) {
        ros::spinOnce();
    }
}

void spin_sleep(ros::Duration duration) {
    spin_sleep(duration, []() { return false;});
}

Then instead of sleeping do something like this:

ros::NodeHandle nh(~);
SimpleTicker s(nh);
spin_sleep(ros::Duration{1});
ASSERT_GT(s.val, 0);
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2021-06-07 00:44:44 -0500

Seen: 206 times

Last updated: Jun 07 '21