ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
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 =).
2 | No.2 Revision |
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 =).