Skip to content
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

Merged
merged 5 commits into from Mar 16, 2017
Merged

Fix/rewrite sync #324

merged 5 commits into from Mar 16, 2017

Conversation

ghost
Copy link

@ghost ghost commented Mar 8, 2017

Use message filters to sync the scans.

fix https://github.com/ipa320/cob_driver/issues/268

}
default:
ROS_ERROR_STREAM(config_.number_input_scans << " topics have been set as input, but scan_unifier doesn't support this.");
return;
Copy link
Contributor

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?

Copy link
Author

@ghost ghost Mar 8, 2017

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.

Copy link
Contributor

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...

Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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.");
}
Copy link
Contributor

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?

Copy link
Contributor

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....

Copy link
Author

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...

Copy link
Contributor

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?

Copy link
Contributor

@fmessmer fmessmer Mar 15, 2017

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

Copy link
Contributor

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?

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));
Copy link
Contributor

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?

Copy link
Contributor

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)

Copy link
Contributor

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?

Copy link
Contributor

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...

Copy link
Contributor

@mgruhler mgruhler Mar 9, 2017

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.

Copy link
Contributor

@fmessmer fmessmer Mar 9, 2017

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)

Copy link
Contributor

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...

Copy link
Contributor

@fmessmer fmessmer Mar 9, 2017

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

Copy link
Contributor

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);
Copy link
Contributor

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might actually be the reason for #249

Also, the above restricts this unifier to be used with a spacing fo 0.5°. This should probably be adapted as well.
Something like "biggest common denominator" but in float ;-)
Added it to #249

delete(synchronizer3_);
break;
}
}
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
else
{
pnh_.getParam("frame", frame_);
Copy link
Contributor

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)
Copy link
Contributor

@fmessmer fmessmer Mar 9, 2017

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();
// }
// }
Copy link
Contributor

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...

@fmessmer fmessmer merged commit 6b57771 into 4am-robotics:indigo_dev Mar 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[cob_scan_unifier] LookupError on start up
2 participants