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

Revision history [back]

click to hide/show revision 1
initial version

Hello, I was just having this problem and thanks to your comments I got a decent solution, so I thought I should share it here. I modified the laserscan_topic_parser to retry to read the topics listed after a delay, so, here's my modification:

bool LaserscanMerger::laserscan_topic_parser(){

bool success = false;
// LaserScan topics to subscribe
ros::master::V_TopicInfo topics;
ros::master::getTopics(topics);

istringstream iss(laserscan_topics);
vector<string> tokens;
copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens));

vector<string> tmp_input_topics;

for(int i=0;i<tokens.size();++i)
{
        for(int j=0;j<topics.size();++j)
    {
        if( (tokens[i].compare(topics[j].name) == 0) && (topics[j].datatype.compare("sensor_msgs/LaserScan") == 0) )
        {
            tmp_input_topics.push_back(topics[j].name);
        }
    }
}

sort(tmp_input_topics.begin(),tmp_input_topics.end());
std::vector<string>::iterator last = std::unique(tmp_input_topics.begin(), tmp_input_topics.end());
tmp_input_topics.erase(last, tmp_input_topics.end());


// Do not re-subscribe if the topics are the same
if( (tmp_input_topics.size() != input_topics.size()) || !equal(tmp_input_topics.begin(),tmp_input_topics.end(),input_topics.begin()))
{

    // Unsubscribe from previous topics
    for(int i=0; i<scan_subscribers.size(); ++i)
        scan_subscribers[i].shutdown();

    input_topics = tmp_input_topics;
    if(input_topics.size() > 0)
    {
        scan_subscribers.resize(input_topics.size());
        clouds_modified.resize(input_topics.size());
        clouds.resize(input_topics.size());
        ROS_INFO("Subscribing to topics\t%ld", scan_subscribers.size());
        for(int i=0; i<input_topics.size(); ++i)
        {
            scan_subscribers[i] = node_.subscribe<sensor_msgs::LaserScan> (input_topics[i].c_str(), 1, boost::bind(&LaserscanMerger::scanCallback,this, _1, input_topics[i]));
            clouds_modified[i] = false;
            cout << input_topics[i] << " ";
        }
        success = true;
    }
    else
        ROS_INFO("Not subscribed to any topic.");
}
return success;}

So, basically, I only changet the return from void to bool and created a local variable (called "success") to determine if any topic was found. Then I put a while loop on the LaserscanMerger class constructor to retry every X seconds:

ros::Rate loop_rate(0.5); //-- 0.5 [Hz] -> 2.0 [s]
while( !this->laserscan_topic_parser() )
{
    ROS_DEBUG("LaserscanMerger: Retrying to detect the topics to subscribe to...");
    loop_rate.sleep();
}

Hope this helps someone =).

Hello, I was just having this problem and thanks to your comments I got a decent solution, so I thought I should share it here. I modified the laserscan_topic_parser to retry to read the topics listed after a delay, so, here's my modification:

bool LaserscanMerger::laserscan_topic_parser(){

bool success = false;
// LaserScan topics to subscribe
ros::master::V_TopicInfo topics;
ros::master::getTopics(topics);

istringstream iss(laserscan_topics);
vector<string> tokens;
copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens));

vector<string> tmp_input_topics;

for(int i=0;i<tokens.size();++i)
{
        for(int j=0;j<topics.size();++j)
    {
        if( (tokens[i].compare(topics[j].name) == 0) && (topics[j].datatype.compare("sensor_msgs/LaserScan") == 0) )
        {
            tmp_input_topics.push_back(topics[j].name);
        }
    }
}

sort(tmp_input_topics.begin(),tmp_input_topics.end());
std::vector<string>::iterator last = std::unique(tmp_input_topics.begin(), tmp_input_topics.end());
tmp_input_topics.erase(last, tmp_input_topics.end());


// Do not re-subscribe if the topics are the same
if( (tmp_input_topics.size() != input_topics.size()) || !equal(tmp_input_topics.begin(),tmp_input_topics.end(),input_topics.begin()))
{

    // Unsubscribe from previous topics
    for(int i=0; i<scan_subscribers.size(); ++i)
        scan_subscribers[i].shutdown();

    input_topics = tmp_input_topics;
    if(input_topics.size() > 0)
    {
        scan_subscribers.resize(input_topics.size());
        clouds_modified.resize(input_topics.size());
        clouds.resize(input_topics.size());
        ROS_INFO("Subscribing to topics\t%ld", scan_subscribers.size());
        for(int i=0; i<input_topics.size(); ++i)
        {
            scan_subscribers[i] = node_.subscribe<sensor_msgs::LaserScan> (input_topics[i].c_str(), 1, boost::bind(&LaserscanMerger::scanCallback,this, _1, input_topics[i]));
            clouds_modified[i] = false;
            cout << input_topics[i] << " ";
        }
        success = true;
    }
    else
        ROS_INFO("Not subscribed to any topic.");
}
return success;}

So, basically, I only changet changed the return type from void to bool and created a local variable (called "success") to determine if any topic was found. Then I put added a while loop on the LaserscanMerger class constructor to retry every X seconds:

ros::Rate loop_rate(0.5); //-- 0.5 [Hz] -> 2.0 [s]
while( !this->laserscan_topic_parser() )
{
    ROS_DEBUG("LaserscanMerger: Retrying to detect the topics to subscribe to...");
    loop_rate.sleep();
}

Hope this helps someone =).