ROS Resources: Documentation | Support | Discussion Forum | Service Status | Q&A answers.ros.org

Georeferencing PointCloud Map

I would agree and also vote for a well specified data format like LAS which seems to have plenty of metadata fields in its header which would be useful for a map manager in the localization stack that would need map generation data like the timestamp and min/max values.

Though, my opinion would be to first formally identify/specify the requirements for a map file and then make sure LAS(or any other candidate) format will cover all of the metadata needs for our use case before making any effort.


For autoware.auto, to not rush a premature decision and maintain the velocity in the development of the localization stack, we can maybe use a simple separate yaml/json metadata file for each map for now while the necessary tools for the new selected format gets implemented/ported in the parallel unless a pcd compatible solution is already available. With a decent level of abstraction on the file handling, migrating to the new file format then should not be hard.

Very briefly skimming through the discussion (I’m in between meetings), one simple hack we can do is abuse the PointCloud2::header::frame_id field by adding a bunch of junk into the string.

For example, "mapL123.567L555.324A23.4"

The pros are that the semantics are mostly correct (you’re specifying the origin or frame of the map), and we don’t have to change existing types.

The big con is that you’re going through a string format which can be a huge mess, however it could be possible to isolate this functionality so that if/when proper map origin support is added, then the change only needs to be in one place.

@cho3 This works for the data once it’s in ROS but not when it’s being stored externally.

Thank you all for the comments.

One of my concern about LAS is that many pointcloud related ROS modules are dependent on PCL, and using PCL friendly format may be useful during development. Converting pcd and las frequently may feel bothersome. Do you have any experience in using LAS with ROS?

To me, this solution seems to be most practical. Also, I agree that we should identify requirements, but after using pcd format for few years with Autoware.ai, I can’t think of any other meta info required at this point (maybe map version in case we do online map updates?). Do you have anything in your mind?

after using pcd format for few years with Autoware.ai, I can’t think of any other meta info required at this point (maybe map version in case we do online map updates?). Do you have anything in your mind?

Yes I am mostly considering the use cases for a map manager that does online map updating but i don’t have anything concrete in my mind right away.

Though If i had to wildly speculate, here are few random thoughts (without knowing what information the map generator can provide):

  • Map generation time stamp: Can be used for some up-to-dateness sanity check.
    • Maybe paired with some expiry date set by the generating authority?
    • Can also be used for time-specific algorithm decisions. (i.e. day/night configurations)
  • Maybe some map context identifier for validation: (i.e. Urban/highway or parking_lot_ID etc.)
  • Min/Max points: Useful information but can also be derived from the cloud itself.
  • If for any reason we want to store pre-downsampled maps, some information on that.
  • Some hardware/source identifier? (if for any reason some specific pre-processing has to be done on the raw maps)

Though none of these seem vital/urgent except for maybe the time stamp and even that can be worked around.

One of my concern about LAS is that many pointcloud related ROS modules are dependent on PCL, and using PCL friendly format may be useful during development.

Just FYI - The Velodyne driver recently dropped the PCL dependency and the point cloud it produces is no longer strictly PCL-compliant. This hasn’t been noticed by many yet because I haven’t released a new version in quite a while but I just wanted to point this out. In addition, we’re mostly talking about a single LAS -> PointCloud2 conversion when loading the map and a single PointCloud2 -> LAS conversion when saving it for map generation. I, personally, do not have any experience using LAS with ROS but it is a very well-defined and maintained standard from the American Society of Photogrammetry and Remote Sensing (ASPRS) which is supported by major scanning companies like Leica Geosystems and Velodyne (through the VeloView Python interface). You can also generate it using LidarView.

1 Like

I’m not at all against using an external file as a quick and simple implementation but I agree with @yunus.caliskan that we should discuss any additional needs and decide on a format that meets them. This is likely a good task for the Maps Work Group.

1 Like

I’m by no means a mapping expert, but given we are only talking about the on-disc format, I think that LAS seems like a reasonable solution.

If that doesn’t work, then a quick and easy solution is to have a .yaml file providing those parameters as well as specifying the filename(s) of the data file(s) containing the map data. This is how the ROS 1 map loading works, and it’s done a pretty good job for the last 13 years.

@mitsudome-r @yunus.caliskan
I am playing around with Yunus’s map_provider and have added a publisher to visualise point cloud in RVIZ2 and a function to read pcd file name and georeference string from a yaml file using yml-cpp.

How will this georeference/string be used? Ideally point cloud map and HD map would share a common reference frame to facilitate use cases like find HD map componets at estimated vehicle position (relative to point cloud map).
Edited - because I maybe don’t understand so well…

I guess loading lanelets map should use this origin to project longitude/latitude data onto?

How will this georeference/string be used?

Here is my idea about map provider nodes:

  1. User specifies ENU origin as global parameter either in WGS84 lat,lon,alt. (It could be in ECEF x,y,z)
    i.e.
$ rosparam set origin_lat 35.6895
$ rosparam set origin_lon 139.69171
  1. pointcloud_map_provider_node
    Input: Map files(PointCloud + YAML)
    Output: pointcloud message in ENU coordinate with origin specified by global parameter

  2. vector_map_provider_node
    Input: Map file (OpenDRIVE or lanelet2) which should already be georeferenced
    Output: vector_map message in ENU coordinate with origin specified by global parameter

This will need to be a parameter set on the map provider node that other nodes can read as necessary, because global parameters don’t exist in ROS 2.

As long as pointcloud_map_provider and vector_map_provider both read the same origin, it should be fine.

I guess this discussion covers the desire not to have global parameters in ROS2

Do we then need to set a hierachy, or launch order, with one map provider node loading the common reference frame and then publishing to the other. Or a third node loading config and publishing to both map provision nodes (and maybe doing map-management logic further down the track)?

For larger maps, how will this impact map mangement? The common origin will change, both maps reloaded and transformed, can we ensure common origin when loading maps in separate nodes?

You need to have a single source of truth for the parameter, but that may not necessarily have to be a node. If two nodes both load it from the same file, and then reject any runtime changes to their copies, it could work.

I think a node publishing the common reference works better. For larger maps, it is not possible to keep a single origin for extended journeys. We want to project onto a common planar reference frame for simplifying motion planning etc, but planar frames become inaccurate when moving a long way from their origin. For small maps its fine to assume no change, but I assume we should design at least for the possibility of larger maps.

For larger maps, how will this impact map mangement? The common origin will change, both maps reloaded and transformed, can we ensure common origin when loading maps in separate nodes?

I think we can use tf framework for that instead of reloading the map.

Assuming we create tf tree according to REP15, there will be “earth -> map” transform, where “earth” is earth center and “map” is ENU origin. If we want to create a new “tile” of map( e.g. map2 frame), we can also create tf “earth -> map2” frame. Then we can calculate position in “map2” frame from “map1” frame via “earth” frame. We might want to have a node to manage “earth”-> “map_n” frames in this case.

Sure, I was thinking that maps were stored as different files for each tiles, so maybe loading is necessary.
But your transform tree is reasonable. I was more concerned with synchronizing the change between the two map provider nodes. Worst case, during updating you have lanelet2 map still using first coordinate frame (while the update is being communicated) and pcd map with new updated coordinate frame. Or is there some method to synchronise nodes?

I was more concerned with synchronizing the change between the two map provider nodes.

I see. I think matter of synchronization is not closed within map providers, but all nodes that subscribe the updated map must be synchronized in that case. I cannot think of a good strategy immediately.

Joshua Whitely has proposed a TF tree for Autoware.Auto.
In it he defines a frame from semantic map to localisation map (SM->LM) published initially by a static transform publisher. How does this influence the georeferencing issue. I assume point cloud maps could still be georeferenced in the way described above (yaml file).

If you have any thoughts, please comment in the linked thread, as the TF tree is being decided (initially for AVP project at least) by the end of the week.

1 Like

If using PCL, we can use the “VIEWPOINT” field in PCL pointcloud file format for storing the sensor origin and orientation. This can further be used for transforming the pointcloud data while loading it.
I haven’t tried this but I faced point precision loss while georeferencing the pointcloud, since PCL uses FLOAT32 datatype and georeference data was quite large. Distortions in georeferenced pointcloud were visible.