-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/rewrite sync #324
Fix/rewrite sync #324
Conversation
} | ||
default: | ||
ROS_ERROR_STREAM(config_.number_input_scans << " topics have been set as input, but scan_unifier doesn't support this."); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I don't like that this can only be done for 2 or 3 scans.
This was better in the old implementation. Is there a way to achieve the same here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this too, but message_filters::TimeSynchronizer is implemented for a max of 9 scans, with a separate impl for every number-of-scanners. I tried but I didn't find a way to make it number-of-scanners-independent. I talked to ipa-fxm about this and he didn't know a better solution either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, the documentation on the wiki seems to state that we can sync up to 9 topics:
C++: Up to 9 separate filters, each of which is of the form void callback(const boost::shared_ptr&). The number of filters supported is determined by the number of template arguments the class was created with.
I'd say, this should be fine then...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ipa-fxm fyi
@mig-em please note if this is superseeding another PR and cross-referene.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, shouldn't we make it in a way then to be able to handle the nine scanners then? Use a vector of synchronizers, maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright, ignore this one: discussed in person.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of completeness: Synchronizer-API is implemented in the same (ugly) way...
else | ||
{ | ||
ROS_WARN_STREAM("Scan unifier skipped scan with " << current_scans.at(i)->header.stamp << " stamp."); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct? We continue
when waitForTransform
times out and throw a warning if not. Or did I mix that up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused as well....
With the Synchronizer we never should need to skip a scan any more...that's the whole point....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Synchronizer does only sync the messages, so it doesn't make any difference for the tf problem...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this is fine.
But: Isn't this still the wrong way around?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, now that I'm looking at it:
We are handing over the tf::TransformListener
object to the projector_
. So in case all the waitForTransform
magic we do in order to make the transformLaserScanToPointCloud
work....maybe we just need to make our listener_
object work!
Because currently it's using the default constructor (http://docs.ros.org/indigo/api/tf/html/c++/classtf_1_1TransformListener.html), i.e. default values for max_cache_time
...maybe we can tweak something here...what also helps qutie often is "wait a little" at the end of the constructor to let the listener_ fill its cache...as we are seeing this problem only in the very beginning...
Also, is this ROS_WARN_STREAM
still seen in the log? Because maybe the better time synchronization now does not give us messy timestamps as the "old" synchronization might have...
Last not least, in case the !waitForTranform
case cannot be avoided by any means...should we return, i.e. skip all scans of current cycle or only skip the scan that failed, i.e. incomplete scan unified
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct? We
continue
whenwaitForTransform
times out and throw a warning if not. Or did I mix that up?
ja is wrong!
typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::LaserScan, sensor_msgs::LaserScan> SyncPolicy; | ||
synchronizer2_ = new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(2), *message_filter_subscribers_.at(0), *message_filter_subscribers_.at(1)); | ||
synchronizer2_->setInterMessageLowerBound(0, ros::Duration(0.167)); | ||
synchronizer2_->setInterMessageLowerBound(1, ros::Duration(0.167)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you choose this number?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
=0.5*(1/12) // half of expected scanner rate at 12Hz (I guess)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, is it safe to assume this is the lower bound? Or would we want to merge scans with a frequency <12Hz as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is 12Hz a configurable parameter for the scanners?
Then we at least should make the computation of the bounds based on a parameter as we might unify scans from other sensors with different publish rate as well...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I'm not sure. There is a parameter about the publish rate in the S300 driver. But: afaik, this is not respected. The new S300 Expert do have an output of about 25Hz (phyiscal max of the scanner) with our driver.
The frequency of the data output depends on the configuration in the scanner itself.
Also, other scanners have other frequencies... And we could actually try to merge scanners with different frequencies. But this gets ugly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make it work for our use-case....either 2 s300 (raw) or 3 s300 (cob4)...then test it...eventually it's cob_scan_unifier anyway
(but add a comment about where the formula comes from, i.e. relate it to expected s300 publish rate)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fine for me. Then we can stick to 12Hz (even though the scanner itself could be configured to send out with less frequency without respecting anything in the driver. we just should not do that).
Then we can stick with the 0.5° spacing in my comment below as well...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I meant after successful testing we could at least introduce parameters to make the scan_unifier node configurable...but those parameters would be scan_unifier parameters and not related to parameters (of the same meaning) of the scanner driver, though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I fully understand this. I just wanted to point out that this is in the end not independent (high expected frequency in the unifier + low frequency in the scanner = no unified scan).
But I'm sure I'm preaching to the choir here :-)
|
||
initLaserScanStructs(); | ||
// synchronizer_->registerCallback(&ScanUnifierNode::messageFilterCallback); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove, this is not used.
unified_scan.header = vec_laser_struct_.at(0).current_scan_msg.header; | ||
unified_scan.header.frame_id = "base_link"; | ||
unified_scan.header = current_scans.at(0)->header; | ||
unified_scan.header.frame_id = frame_; | ||
unified_scan.angle_increment = M_PI/180.0/2.0; | ||
unified_scan.angle_min = -M_PI + unified_scan.angle_increment*0.01; | ||
unified_scan.angle_max = M_PI - unified_scan.angle_increment*0.01; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete(synchronizer3_); | ||
break; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess there is actually no need to switch...you could just delete
both...
XmlRpc::XmlRpcValue topicList; | ||
|
||
// TODO short parsing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to list retrieval: http://wiki.ros.org/roscpp/Overview/Parameter%20Server#Retrieving_Lists
} | ||
else | ||
{ | ||
pnh_.getParam("frame", frame_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just use "default version" (nh.param<std::string>("default_param", default_param, "default_value");
) ?
* output: - | ||
*/ | ||
void scan_unifier_node::initLaserScanStructs() | ||
void ScanUnifierNode::messageFilterCallback(const sensor_msgs::LaserScan::ConstPtr& first_scanner, const sensor_msgs::LaserScan::ConstPtr& second_scanner) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer scan1
instead of first_scanner
, scan2
instead of second_scanner
....
// | ||
// config_.number_input_scans = config_.input_scan_topics.size(); | ||
// } | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could/should be removed...
Use message filters to sync the scans.
fix https://github.com/ipa320/cob_driver/issues/268