-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Feature Request: Custom/Virtual Obstacle Layer #3017
Comments
I would indeed, I haven't looked in excessive detail how this works exactly, but the concept seems good to me to have in Nav2 and would be actually very convenient for testing purposes (mainly). Curious though for a more production reason what you might be doing with this? I'd want to know
But the general principle seems good. |
Thanks @tonynajjar. My virtual layer repo is a bit outdated demo package. Sorry about that 🙋🏻 I will let you know when I'll get some free time to upgrade the virtual layer by adding some other features that might help:
Regarding the production use @SteveMacenski , I think people are using this plugin differently. Personally, I am using it (not with demo project) to define I have developed also some navigation plugins (global and local planning) that I want to make them compatible with ROS2 and Nav2 🤖 🚀. I will let you know in slack or in another Github issue/thread about this work. |
I might recommend just adding a "add" and "remove" service and part of the request includes some string or int index for the objects. Not using pub/sub.
Great to hear it and look forward to hearing about it! |
@tonynajjar so what's your plan here? Remake something using that as a reference or wait for it to be ported and we can go through some design reviews to patch it up? Or should we start design reviews here now with the intention of including the final results into Nav2 itself? Its also totally fine if you keep it separate, no need to put it into nav2 if you don't want. We can always add it to our Navigation Plugins list in our docs so that its searchable for users (and possible a tutorial if you're interested in that?) |
I work on the same project as @tonynajjar and can give some context on our use: We use multiple robots in a shared environment. There are some cases in which the onboard-sensors of robot A cannot fully see robot B. Thus, robots share their location (and planned path) with each other. Now, to help with local and global planning, we want to put the footprint of robot B on the costmap of robot A. For this, robot A would publish the received footprint of robot B on a topic, and this new plugin would then add it to the costmap. I think services would add too much latency here, in case robot B is moving. |
@jplapp I will make sure that there is no incompatibility with current version when integrating new updates to the demo package. 😀 |
At the end of the day, services are just a paired request and response, over the same network interfaces and can be run with QoS settings like topics. I don't think that would be problematic at all and I think it is entirely necessary so you can (1) verify that an obstacle was successfully added to the scene and (2) you can verify deletion or moving of obstacles in the scene. Especially in the case of multi-robot networking where things could drop out, it is very important you know what was successfully added and what wasn't. Maybe for the long-range planning application it isn't critical, but we need to act like any user of this work if in Nav2 has critical information that could prevent a dangerous situation. Otherwise, you could stream topics that are missed and never know that you're not going to avoid and obstacle / zone until its too late. Also if a service call fails, you know as a fact that Robot A didn't get Robot B's footprint, so you can try to retransmit. You'd never know that if you didn't have a service. I think services are the right choice for the interface design. |
What do you think of having a |
Thanks a lot for your insights @SteveMacenski . I have so far mostly taken inspiration from the costmap_converter often used with the TEB planner, which converts a costmap into polygons and publishes them as a topic - and thought of what we want to do here as the opposite direction. Using services will allow the sender (robot B) to know that the communication is broken. However, it might not suffice to prevent the dangerous situation: If communication is broken, what can robot B do with this information? It can't tell robot A to stop. So maybe there are two usecases here:
In case 2), the sender (robot B) constantly produces new information. So, over the (unstable) network I don't think there's a need for retransmitting, as new information will be available soon anyway. For such constantly updating data as in case 2), other obstacle layers also receive their (critical) input via topics, so what would be different here? There are some usability advantages of topics, such as logging with rosbags, that would be quite helpful for us. |
The client knows it failed to send it, so it can (1) retry so that you make genuine attempts to get the message over (2) log warnings to debug later problems in the fleet. There are many things that knowing that Robot A failed to send the message enables for reliable systems. Its not about what the other robot's server is doing with that information (because it didn't get the request, so it knows nothing) its about what the client can do to improve the chances of it working or introspecting the results. And with a service, you can know which IDs were successfully added so you can remove them later and not waste networking resources on trying to
Introspection of services is on it way soon actually https://discourse.ros.org/t/rep-2012-service-introspection/26079/4. But like I said above, you could at least log failures with services that you couldn't with topics. Also, if you don't finely handle your QoS on the polygons topic, you could end up backfilling and having a huge amount of memory overhead and/or instant network traffic flooding the pipes when a connection is re-established for old messages trying to pass through - since I imagine you would want to have some kind of transient-local properties if just streaming a topic on separate wireless devices of this nature. For your examples
But for either 1/2, deleting is also an important thing to get feedback on, not just additions. So services again seem to me to make sense as the interface to get acks back that 'Yes, Object 43432 is removed'. I suppose we could support both services and topics, though not my ideal outcome. I would want clear warnings to users informing them that topics are not recommended, but may be useful in certain circumstances. Separate of this topic, but I also wonder if it would be nice to have a |
I'd like to avoid doubling the work with @GMahmoud. To decide on a way forward @GMahmoud can you let us know: 1- When do you expect to have the ROS2 port ready? |
Hello @tonynajjar I will start doing some update this weekend. Let me know 😃 |
Hello !
If you want to take a look at it. @tonynajjar I will let you know when I start to work on Nav2 Cheers |
Via services? Yes, that was my thought as well 😄 I looked very briefly at the code, there's alot going on there. If you were to define a But I very look forward to this, this is a good compliment to the keepout filters. Sometimes a mask makes sense, but often a polygon or vector shape makes sense too! If we add the services to the Python3 Simple Commander, it'll be stupidly easy to make testing demos with randomly generated obstacles in a costmap, without having to manually create a map. Just open a blank costmap and generate random stuff in random spots to insert. |
I agree with you about defining only outerline of a So I want to make the virtual_layer more generic and support also I will surely adapt my integration to nav2 use cases 😺, if you need to use only a simplified polygon.
Agreed 👍🏻 (Added to task list) |
Please check the following design considerations how this feature could be added into Nav2 stack. My initial idea was to maximum re-use the existing messages (like
The design seems to cover all use-cases from the ticket discussions, and I do hope, it might be suitable for future utilization by other scenarios. The proposed initial feature design in attached as VO_design_20230131.pdf. Any comments/feedback are welcoming. |
I don't think any external server is required, but is certainly an option. We could have the layer simply take in a file itself which populates the information. A centralized server for the maps are helpful because there are many consumers of the map (costmaps, localization, collision checkers, visualization, etc). If we think there will be many consumers of the virtual obstacle information, then a centralized server is sensible. Else, loading from file is fine. The layer should be the one managing the set of polygons and operating upon them, the only role of a server should be to serve that information up to the layer from a file. Think of the obstacle layer: sensor data is sent to populate in the layer itself (I think the idea of having more processing in the external server was why you mentioned the If you have a vector of points making up a polygon stored in a layer, it can be used to fill in the costmap2D entries of the master grid on request (or retain an internal grid structure of the polygons, I suppose, depending on what's more optimal from an update cycle perspective). There's no real need to be thinking about ROS interfaces like I don't see a strong need to support multiple subclass shapes (eg squares, bars) separately as For circles, I think we'd need some special case for sure. Another question is about pose of the shape. If we want to set a box of points making up a 1m box, do I need to transform them to the pose already or can I have a pose of the center of the shape. I think that's more relevent for the The design I would have in mind is a server to read the polygons from file, if provided. That publishes to a topic that the costmap layer receives. The costmap layer either stores the vectorized information to populate in the costmap each cycle, or populates it immediately into a rastered map for use (whatever's more efficient). Services are added to get/set/remove the polygons from the costmap layer. An aside, but the |
The last branch @GMahmoud posted looked overall pretty good to me from a quick scan. I can't speak to the efficiency and certainly the parsing from file we discussed having done potentially by an outside server, but that's overall a good starting point. I wouldn't reinvent what's done well for us, if after some analysis you agree there are lessons to be taken from it. |
Regarding the server vs layer model: the main question was in that - do we plan to vectorize Costmap2D-s, or Going a little further, I might suggest that
However, this only fair if we have right model of usage/usecases for that.
I actually, I don't mind any of both options, so the question is what model do we plan to have in Nav2: vector objects in costmaps, or vector object in costmaps + vectorized Nav2 maps everywhere? Next item to discuss - is shapes design.
In this case we to utilize only polygons, the design will be really simple, and we do not need to have that universal If we will decide have to support some other objects in the future, I see two major options there:
I've selected the second one, to have an ability to expand the number of types of vector objects supported. If we do not need it (we'd like to leave only polygons and circles as it was made for Collision Monitor, or even only polygons w/o circles), the best option is O1.
Hm... that is really interesting. I thought, it actively used in Costmap2D-s. But anyway, no one forbids us to revive this format, if we will really have a needs for it. |
I think that's out of scope of what we define as what a "costmap filter" is in the documentation. Its a rastered map of cost. The vectorized information is not a rastered map and there isn't the same kind of This can be thought of more as a normal costmap layer as a vector option instead of rastered maps, which that is a more sensible option. I had not at least initially considered the use of this feature for anything other than obstacles / costs in the costmap for navigation (e.g. Speed limit zones as polygons). How would that analog for the costmap filter info be send here for the multiplier, base, and action to use for the polygons? I don't think that was initially in the presentation.
But who would be the downstream consumer of that? I would think it would be the costmap, so having a layer that adds the geometries is no different of a workflow (its just who's hosting that particular service). Being able to just create a costmap and add some random shaped objects is inherently useful for benchmarking and analysis instead of having to create rastered maps of shapes to store offline. The major reasons why I'm thinking this design:
I'd start with arbitrary polygons, lines, and circles. Honestly the most common use here is going to be boxes drawn on screens for keepout zones or speed zones or something by a non-trained user on a web GUI that's going to be propagated down here during robot setup.
It is being used, but mostly with the details hidden in the costmap subscriber and costmap publisher objects. There's no need for it at all, the OccupancyGrid messages do the same. They added in a So tl;dr
Edit: Ahhh, I think I understand a little bit better now your thinking, You want to use the default costmap filter plugin layers, don't you? You're seeing this as doing the pre-work for the layers so that the same speed and keepout zone costmap filters can be used, but the rastered costmaps are coming from this external server? That was unclear since the presentation shows a new |
Sorry for interjecting in the lovely design discussions, I would just like to mention that we found another application of such a costmap layer: We have a pallet-picking forklift-looking AMR; to be able to pick up a pallet aka driving into a pallet, we need to clear the region on the costmap (not centered at the robot) where the pallet is. I want to point out that even if we were to add the functionality to clear any custom region in nav2_costmap_2d, that would not be enough because the pallet is still there so the occupied costs will reappear. Therefore we actually need an extra layer to make the pallet disappear from the costmap. P.S: Feel free to let me know if I missed another solution Nav2 offers for this problem |
You have the option in a costmap layer to "override" cost instead of taking the maximum. So you can have the detector layer of your pallet that you'd be using to clear the costmap as the highest layer and it would wipe out all the sensor measurements as long as you're detecting the pallet there (or whatever your logic). That's probably the easiest way and only ~200 lines of code. |
Per our discussion in the WG meeting:
|
@tonynajjar, thank you for the example provided above. No matter even if you will hide the data from sensor as Steve, suggested, I see here an additional use-case application of this feature: it is dynamically hiding some underlying objects in costmaps. This, BTW even more strongly speaks to the side of standalone Costmap2D layer running there for performance reasons. So, regarding the design discussions, to continue the ideas from WG meeting, that @SteveMacenski pointed out, we have a tradeoff between two designs:
D2. Vector Object layer on Costmap2D operating only with costmaps
Collecting all approach proc and cons, and if we are no requiring in OccupancyGrid maps "vectorizing" as of today intention, it is more reasonable to prefer "D2" over it. Otherwise, in the future, if we need to have to add VO to OccupancyGrid maps someday, the logic could be moved-out to operate separately as of VO-server. It seems not a big issue in that case. Later, I will prepare design PPT update. with more details and attach there. |
Updated according to latest discussions, feature design is attached as VO_layer_design_20230203.pdf |
Thanks for the proposition. The detector layer is actually plain STVL, which also detects other obstacles which we do not want to clear. Additionally, we obviously can't detect the whole pallet with STVL so we do need to generate a custom polygon. |
You mean the costmap filters (keepout + speed), right? To be able to do other non-just-cost tasks with the polygon's values
It would likely be stored either way (e.g. in the costmap), so its more about the transport.
But isn't that what the costmap filters are for? I don't think that's a con, that's just a feature that already exists.
I think this was miscategorized. That's a con for D2. D1 is far more simple conceptually and enables re-use of existing costmap filters just with the input being from the vector object server, not the map file. |
Not certainly in that way. In case of StaticLayer, we will re-use one of the existing costmap layer to make and apply (to master grid) raster costmap made from obtained input
Yes, I was not entirely accurate. The main performance pitfall we may get when we have a large
Yes, but as I understand costmaps are using The other question - do we really need these abilities?
D1 is more simple conceptually, but as I recall we've discussed, that this approach might change the concept/meaning/understanding of |
Why? The keepout filter would be more flexible, and the static layer doesn't allow for shapes to represent other things like speed zones. Its in effect the same thing, but doesn't allow remapping of values potentially stored in the shape files. If we're going to allow the user to have shapes with other things like Speed or Triggering, why use the Static layer (not a costmap filter) instead of the Keepout filter -- when all others are costmap filters? OK what I'm thinking, since I think we're generally in the first ballpark as each other but missing on the finer details:
Everything in Nav2 is an Occupancy Grid, a costmap is an occupancy grid. There's not difference. The costmap message should be deleted and shouldn't be considered here in any differing nature. |
Now I looks understand well your intention: to use Keepout Filter for resulting costmap updates.
Not sure, why do we need to put each shape into separate file? If everything will be described as one ROS-param YAML, having all-shapes in one list (like we have for Collision Monitor), could it be an option? Moving forward, we need to have separate input topic, each one per each type of shape: Polygon, BrokenLine and Circle. They e.g. could be automatically generated by user-defined prefix. Something, if we have name of VO-server to be equal to
Each topic will have Similar situation will be for shapes adding/removing services. We need to have each type of service per each shape to add, but we can get by with one removing service for all shapes (removing by
I have some doubts about the case when we have large map with (large) restricting polygon + dynamically moving/updating another polygon and small rolling window for resulting costmap, like depicted below: Isn't idea with centralized VO-server, publisging whole rasterized OccGrid map for the polygons (D1 architecture), will have a performance pitfalls comparing to separate VO-layer (w/o VO-server architecture D2) in the costmap? |
How would you communicate to the client which shape should be used for which application to interpret the costs?
Why? We should use a single interface for the shapes. Also I think you mean services so that you can get a request/reply to know the update / removal / addition was made. I'm not sure why messages for the polygons would need to exist if the server is reading from file and populating the occupancy grid.
As well, its worth doing an experiment. I don't think it matters at all what the size of the polygons the changes have, because either way we need to recompute the occ grid and then publish out the entire costmap again (unless we use the updates API - which I'm not sure the costmap filter implement?) |
Performance estimation results of using centralized VO-server (duplicating from Slack, just for future use): I've created some kind of simple VO-Server node in Nav2 preparing required size of mask and publishing it regularly. Then enabling KeepoutFilter in local costmap with published mask.
Both mask publishing and receiving times are directly proportional to mask size. However, map publish time is ~40-100x times higher than map receive time, so let's focus on it. As was expected, KeepoutFilter process time was not dependent on mask size, as we are processing area inside rolling window.
which is insignificant in our case So, the timings are more than suitable for dynamic objects support on centralized VO-server side. |
Next update of feature HLD is here: VO_design_20230222.pdf.
So, it could be used a |
For the API:
|
Agree, 8-bit value should be OK, since we won't use each own unique priority per each vector object
The priority is made for the case when we intentionally want to make the order of intersections of the vector objects. This is the case if we want to some objects with lower value to intentionally to lay over the ones with higher values while using Indeed,
Initially, I thought about making some kind of "holes" inside vector objects, and filling them with This could be resolved by adding some new essences like "rings", initially proposed in the "virtual_costmap_layer". But I'd here rather more inclined to an extra
Thanks for pointing this out!
Yep. Moreover, if Also, |
One more thing about the design.
I remember there were some points why each shape is better to describe in its own file, were on the call. But I can not recall exactly is there any specific point why we should do it, if we are using one VO-server per specific costmap layer/filter? |
I don't think any priority is needed. If you have intersecting shapes, A very common workflow when deploying robots is to map the space and then have a facility manager (or someone) sit with an ipad and just drag boxes onto the map to mark docks, safety zones, aisles, etc for semantic information to use in navigation later. In fact, I'd really like as part of this after we get done with the MVP of the server is to develop the tools in rviz to essentially allow for that workflow and save to a file for use.
But what are the specific mechanics at which you'd make transparency? I don't think its possible with the information you have available. You don't know what value of cost 0-255 would remap to "do nothing". 0 could be 0% speed or 0 could be trigger the binary filter -- we simply cannot know.
I figured their own files would be most sensible because of the fact that if you're deploying |
just following up, is this actively being worked on or on pause at the moment? |
Working on the feature is in active progress. There is ~90% of main algorithms code done. After combing-up stage, I plan to open draft PR on it. |
Hello @AlexeyMerzlyakov and the whole maintainers team. |
Hey, in our use case, we would like to use https://github.com/GMahmoud/virtual_costmap_layer with Nav2. Would you consider it a generic costmap layer that could be part of Nav2? Could it also be an extension of the Obstacle Layer?
We could work on contributing it.
@GMahmoud FYI
The text was updated successfully, but these errors were encountered: