Replies: 8 comments 10 replies
-
This proposal is very throughly thought and neatly designed, thanks for the work. I really like the Proposal B. Proposal A is puts a lot of map loading logic on client side. This makes it hard if people want to add different clients. Potential optimizationsI think the further optimizations can be made by providing precomputed voxelgrid structures to the Here ndt matcher is initialized with the map points: pcl::shared_ptr<pcl::PointCloud<PointTarget>> map_points_ptr(new pcl::PointCloud<PointTarget>);
pcl::fromROSMsg(*map_points_msg_ptr, *map_points_ptr);
new_ndt_ptr->setInputTarget(map_points_ptr); BottlenecksIgnoring the transmission cost, here is the most time consuming part. ROS to PCL conversion pcl::shared_ptr<pcl::PointCloud<PointTarget>> map_points_ptr(new pcl::PointCloud<PointTarget>);
pcl::fromROSMsg(*map_points_msg_ptr, *map_points_ptr); Here the conversion of the messages cost some significant milliseconds depending on the size of the point cloud. Voxel grid constructionnew_ndt_ptr->setInputTarget(map_points_ptr); Here, it calls this function https://github.com/tier4/ndt_omp/blob/tier4/main/include/pclomp/ndt_omp.h#L127-L135 inline void
setInputTarget(const PointCloudTargetConstPtr &cloud)
{
pcl::Registration<PointSource, PointTarget>::setInputTarget(cloud);
init();
} I'm guessing the And it finally the init() https://github.com/tier4/ndt_omp/blob/tier4/main/include/pclomp/ndt_omp.h#L326-L334 : /** \brief Initiate covariance voxel structure. */
void inline
init()
{
target_cells_.setLeafSize(resolution_, resolution_, resolution_);
target_cells_.setInputCloud(target_);
// Initiate voxel structure.
target_cells_.filter(true);
} So if we could precompute these voxel data structures for each grid (from the Proposal B) then this initialization would be near instantaneous. How to overcome bottlenecksAs long as we are using native PCL, I think we can't avoid the And similar can be said for the initialized voxel structure too. But I am open to your opinions on this. Proceeding without optimizations firstI think to ensure compatibility with current stack and enable initial implementation quickly, your current plan is sound. My summary of the graph TD
NdtClient["NDT Client"] -->|"Query for point cloud map grids <br> around a 2D pose and a list of currently stored ids"| MapServer["Map Server"]
MapServer["Map Server"] -->|"Deliver a list of point clouds with their ids <br> around that 2D pose <br> excluding the id's client has stored"| NdtClient["NDT Client"]
Extra points:
Simplifying the client implementationMaybe we can provide a helper class for the client. Role would be to keep track of the id's with the protocol defined in |
Beta Was this translation helpful? Give feedback.
-
Another way of handling this is to make map loading module a library instead of a node. Matcher node would use this map loader library to load maps. Pros:
Cons:
|
Beta Was this translation helpful? Give feedback.
-
@yukkysaito @mitsudome-r @YamatoAndo @xmfcx Currently, I would prefer proposal B, as I believe it is better to focus on making the clients' implementation as simple as possible. If no one has any disagreeing opinion, I would make B as a final decision and close this discussion. |
Beta Was this translation helpful? Give feedback.
-
It seems that there are no other opinions or alternative plans. |
Beta Was this translation helpful? Give feedback.
-
This may be late but to add to the discussion:
|
Beta Was this translation helpful? Give feedback.
-
@yukkysaito @mitsudome-r @xmfcx IntroductionPrevious discussions only considered scenarios where the client required a spherical area. And we chose proposal B because it makes the clients' implementation as simple as possible. However, some nodes (e.g. Sequential whole area loading scenarioHere we briefly introduce map loading scenario added from previous discussion. This scenario considers a case when a node (e.g. In this scenario, client node can’t use Partial area loading implemented by Proposal B to get a whole area from the available PCD map because client node does not know the whole area size. We need to pass the information of PCD map to client. Proposed architectureWe want to add this architecture, almost equal to proposal A. A client that want to use the new interface ("client 1" in the figure) first subscribes a message (see here for the definition) that contains a dictionary of each grids' ID and its region information.Using this information, the client selects the maps it wants and throw the query to the map_loader with autoware_map_msgs/srv/GetSelectedPointCloudMap. map_loader loads the required maps and send them back as a response. In the Sequential whole area loading scenario, the client node select PCD map cell's ID one by one, using the given metadata list. Then, the client requests the map ID and map_loader serves PCD map corresponding to PCD map cell's ID. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
@xmfcx |
Beta Was this translation helpful? Give feedback.
-
We, TIER IV, would like to propose a new architecture for point cloud map loading.
Goal: Expand the size limit of the point cloud maps to improve the scalability of Autoware
Introduction
Current Autoware is not scalable in terms of the size of the map, since it loads the whole point cloud (PCD) map at once. As far as we know, the size limit of PCD map in the current Autoware is around 2GB which is determined by the maximum size of a topic message in cycloneDDS. Thus, we are working on a new type of algorithm for loading a PCD map: dynamic map loading (DML).
dynamic_map_loading-2022-06-29_15.19.17_10x.mp4
Through our experiment, however, it turned out that the current interface is not suitable for efficient DML. For example, the naive DML (shown in the above video) newly loads all the PCD maps within the range of 200m from the ego-vehicle every several seconds, which may be too inefficient to perform in real time on limited computational resources.
Thus, we propose a differential DML, which reuses the overlapped PCD grids from the previous loading area to reduce the computation. For example, in the case below, the naive DML loads 38 grids (shown in the gray area), while the differential DML loads 6 grids (shown in blue). Note that the differential DML has to remove 6 grids (shown in red) in this case.
Unfortunately, the current map interface cannot provide sufficient information for client nodes to handle this complex management of PCD maps.
Thus, we, TIER IV, would like to propose to the AWF community a new interface to enable more flexible map loading.
Note that this is a proposal for an additional interface (service) as an option, and is not intended to remove any current interface.
Here we also assume that the PCD map is divided beforehand, e.g. into 20m x 20m grids (see an additional proposal for map dividing format).
Possible map loading scenarios
Here we briefly introduce possible map loading scenarios.
Whole area loading
This is the only scenario that the current Autoware supports, in which the client nodes load the whole available map at once.
As long as the size of point cloud map does not induce any issues (i.e. communication size limit mentioned above), this scenario would be the most simple solution.
Note that you can perform whole map loading in the same way as in the current Autoware, since the proposed architectures have no influence on the existing interface.
Partial area loading
This scenario considers a case when a node (e.g.
pose_initializer
) only wants a limited area from the available PCD map. We assume that, given the area query, the node loads the PCD grids that overlap with the area query. This scenario may be needed when the point cloud map is too large to load at once.Differential area loading
In this scenario, a node (e.g.$M(t)$ for $t=t$ with differential area loading, the client node at $t=t+1$ loads $M(t+1) \backslash M(t)$ and unloads $M(t) \backslash M(t+1)$ where $A/B = \lbrace x \in A | x \notin B \rbrace$ .
ndt_scan_matcher
) loads additional PCD grid maps (shown in blue) as well as removes maps that are no longer necessary (shown in red) at each step.By reusing the maps that the node already has (shown in grey), the node can significantly reduce the computation that occurs in loading and preprocessing the map.
If we assume that a client node wants a set of map grids
As discussed above, this scenario is needed when the point cloud map is too large and the partial loading scenario is not efficient enough.
Proposed architectures
We have two proposals, both of which can achieve the above-mentioned three scenarios. Since they both have their pros and cons, we would like to ask for your opinions from various perspectives.
Proposal A: sending ids as a query
The architecture of proposal A is shown below. A client that want to use the new interface ("
client 1
" in the figure) first subscribes a message (see here for the definition) that contains a dictionary of each grids' ID and its region information.Using this information, the client selects the maps it wants and throw the query to the
map_loader
with autoware_map_msgs/srv/LoadPCDMaps.map_loader
loads the required maps and send them back as a response.Note that in this case, we are also considering creating a library that covers all three scenarios mentioned above.
The three scenarios mentioned above can be achieved as follows:
/map/pointcloud_map
topic as before (as shown inclient 2
in the above figure).Pros:
Cons:
Proposal B: passing area and map ids that the client already has
The architecture of proposal B is shown below. In this proposal, the client (
client 1
in the figure) sends the following two data as a query:In case of
mode=0
, given the above two data, themap_loader
returns all the map grids and their IDs that overlaps with the queried area.In addition, when the client wants to use differential map loading (e.g. for more efficient computation), the client should additionally sends the following query:
In case of
mode=1
, given the above three data, themap_loader
returns...The three scenarios mentioned above can be achieved as follows:
/map/pointcloud_map
topic as before (as shown inclient 2
in the above figure).already_loaded_ids
empty in this case)The differential DML is expected to use
mode=1
.(See also: autoware_map_msgs/srv/LoadPCDMapsGeneral)
Pros:
Cons:
Other candidates that we had in mind
See here
Beta Was this translation helpful? Give feedback.
All reactions