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

Provides a default ToRoadPosition/FindRoadPosition implementations using kdtree data structure #517

Merged
merged 24 commits into from
Jan 18, 2023

Conversation

francocipollone
Copy link
Collaborator

Part of #516

Summary

Provide a base implementation of the RoadGeometry::ToRoadPosition and RoadGeometry::FindRoadPosition methods
that uses a kdtree under the hood for improving query times.

Pendings

  • Implement it for the FindRoadPosition method.

@francocipollone
Copy link
Collaborator Author

For finding roads within a given radius we will need the kdtree to provide range a search queries. So I'm gonna continue working on that and then go back to this PR.

Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
@francocipollone francocipollone force-pushed the francocipollone/improve_road_geometry_queries branch from b685725 to f83507f Compare August 16, 2022 17:06
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
@Voldivh
Copy link
Collaborator

Voldivh commented Aug 23, 2022

For some preliminary results on this implementation, take a look to #516 .

Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

PTAL and let me know.

Voldivh and others added 6 commits August 31, 2022 13:04
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
…nto francocipollone/improve_road_geometry_queries
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
@Voldivh
Copy link
Collaborator

Voldivh commented Sep 8, 2022

After some discussion regarding the design process of this feature, we agreed to create a template for maliput::geometry_base::RoadGeometry in order to give the users/builders of the road geometry a way to select which strategy to use (atm BruteForce and KDTree would be the only available). However, this modification implies several changes in additional parts of the code that does not need, nor care about the strategy to use.
So far I have needed to modify all the forward declarations of the class (Ex. geometry_base/junction.h and geometry_base/branch_point.h) and the mock up class of road geometry and it's use on all the tests (check this branch.
Due to this extensive changes needed to implement this feature using templates, I'm wondering if it is actually the best option to go. Some ideas that were in the air during discussion that would still solve the problem can be:

  • Create a method like RoadGeometry::SelectStrategy() that can be called after building the road geometry (before the init function we need to call at the last moment of the builder).
  • Use an enum to identify the strategies and give the constructor an additional argument that would be use on the constructor definition.

I would like your input on this in order to select the appropriate solution for this particular issue @agalbachicar @francocipollone . I would like to explicitly say that this modification to our design would not affect the fact that the strategies are children classes from a base parent class (just like we discussed)

Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

Unsolicited review. PTAL

@agalbachicar
Copy link
Collaborator

@Voldivh I started to review the code before I had the chance to notice about your comment. Sorry about that. I might be missing something but I don't understand why you need to templetize also the Passkey in the Branchpoint and in the Junction classes. That makes no sense at all at a glance because you are only templetizing the constructor, not the entire RoadGeometry.

That said, we should keep in mind that this code will not be executed directly by backends, and we are trying to remove code duplication in the backends by offering in higher levels a common and performant solution. So it is OK to have more and potentially not that trivial code here in favor of not having to replicate cumbersome code in every backend implementation.

@francocipollone
Copy link
Collaborator Author

That makes no sense at all at a glance because you are only templetizing the constructor, not the entire RoadGeometry.

@agalbachicar You can't have a templatized parameter in the constructor that is not deductible by argument. And in this case we are not passing any argument so templatizing only the constructor isn't an option.

@francocipollone
Copy link
Collaborator Author

That makes no sense at all at a glance because you are only templetizing the constructor, not the entire RoadGeometry.

@agalbachicar You can't have a templatized parameter in the constructor that is not deductible by argument. And in this case we are not passing any argument so templatizing only the constructor isn't an option.

As a workaround, we could use a Helper argument like:

template <typename T>
struct Helper {
    using type = T;
};
// To be used:
RoadGeometry(Helper<BruteForceStragegy>{});

But it's a bit cumbersome.

@agalbachicar
Copy link
Collaborator

Oh, ok. Alternatively we could have 2 constructors:

  • One that receives a std::unique_ptr
  • One that calls the other with std::unique_ptr

That will remove the template argument which is an inconvenient decoration at this point.

Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
@Voldivh Voldivh requested a review from agalbachicar September 8, 2022 18:29
@agalbachicar
Copy link
Collaborator

Sounds good to me. Let's proceed with the other comments now! Thanks @Voldivh

Copy link
Collaborator Author

@francocipollone francocipollone left a comment

Choose a reason for hiding this comment

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

Added some suggestions on docstrings

…ments

Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

Checkpoint. Please wait until I finish with my review. I did not have the chance to full review the PR again.

Comment on lines 120 to 126
std::set<api::LaneId> maliput_lanes;
/*std::transform(maliput_points.begin(), maliput_points.end(),
maliput_lanes.begin(),
[](auto point) {return point->lane_id().value();});*/
for (const auto& current_point : maliput_points) {
maliput_lanes.insert(current_point->lane_id().value());
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Consider trying with std::transform once more now that you'll store raw pointers: #517 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Solving in favor for deferring the change to use pointers instead of ids.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It isn't possible as interestingly std::set only offers iterators that are constants: 😞

See https://en.cppreference.com/w/cpp/container/set/begin

Because both iterator and const_iterator are constant iterators (and may in fact be the same type), it is not possible to mutate the elements of the container through an iterator returned by any of these member functions.

Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

I have completed the review.

Let's move forward with the comments and then make sure that downstream the backends using geometry_base (malidrive - multilane) opt in for BruteForceStrategy and share the same results as before. That should provide some guarantees when tests pass that things remain the same at the integration level.
I will also suggest to add test coverage in a follow up PR. I can suggest a few tips to make things easier.

Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Comment on lines 77 to 79
maliput::api::RoadPositionResult ClosestLane(const maliput::math::Vector3& point) const;

std::set<maliput::api::LaneId> ClosestLanes(const maliput::math::Vector3& point, double distance) const;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Missing comment maybe?

Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

Thanks for addressing most of hte commetns .There are still some, ptal @Voldivh, great job !

Signed-off-by: Voldivh <eloyabmfcv@gmail.com>
Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
@@ -168,6 +206,7 @@ class RoadGeometry : public api::RoadGeometry {
std::vector<std::unique_ptr<Junction>> junctions_;
std::vector<std::unique_ptr<BranchPoint>> branch_points_;
api::BasicIdIndex id_index_;
std::unique_ptr<StrategyBase> strategy_;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am tempted to initialize BruteForceStrategy by default and let the user initialize other by demand.
(Note that otherwise if InitailizeStrategy isn't called then the DoToRoadPosition and DoFindRoadPosition will throw because strategy_ being nullptr).

It wouldn't impact current backends and it doesn't impose a method call when you simply want to use the standard one.
Wdyt? @agalbachicar

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's OK to keep the status quo but I think the default implementation must be the KDTree based one.

Copy link
Collaborator Author

@francocipollone francocipollone Jan 17, 2023

Choose a reason for hiding this comment

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

The thing is that the KDTree strategy should be initialize after the RoadGeometry is populated. So, we need to user to trigger the initialization while with the brute force one we can just define it as default value of strategy_.

Also the user should indicate the sampling step desired when using the kdtree strategy.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sounds good then.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
agalbachicar
agalbachicar previously approved these changes Jan 17, 2023
Copy link
Collaborator

@agalbachicar agalbachicar left a comment

Choose a reason for hiding this comment

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

LGTM

Signed-off-by: Franco Cipollone <franco.c@ekumenlabs.com>
@francocipollone
Copy link
Collaborator Author

Next steps:

@francocipollone francocipollone merged commit 50b45c0 into main Jan 18, 2023
@francocipollone francocipollone deleted the francocipollone/improve_road_geometry_queries branch January 18, 2023 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants