-
Notifications
You must be signed in to change notification settings - Fork 19
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
Support large vrt from ArduPilot SRTM1 terrain server #38
base: ros2
Are you sure you want to change the base?
Conversation
cd9e531
to
d90c7ab
Compare
57f7900
to
9bc305b
Compare
I attempted to try loading the sargans color tif file at the same time as the SRTM1 dataset for the same area in 9738ba8. The pixel resolutions are different, and the data raster sizes are different. The maps don't align, and it causes the grid_map iterator to crash with a floating point exception. I haven't really been able to dig into it yet, but perhaps this would be OK to merge as-is without the capability to handle layers with different sizes/resolutions/datums? As far as I can tell, this branch does not cause regressions in the original files. I saw your open PR to align multiple maps may be related... |
Exactly, you would need #36 to align multiple DEMs |
9738ba8
to
58261e1
Compare
dd07c44
to
b859878
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry that it took me a while to review this.
Thanks for the amazing effort. I think the fact that we can load VRT into grid_map_geo is fascinating!
I have some comments that might be worth discussing.
- I would prefer if we could utilize tf as the primary mechanism of aligning maps.(at least for now) This way we do not need to worry about alignments or storing the origin position of the tif map. It would just automatically align in rviz.
- The maximum map size needs to be always defined? Could we only use it when specified?
- I am a bit worried that the
map_publisher
will become more and more complicated as we add features. Could we have a simpletif_loader
that demonstrates how you can use the API, and maybe a standard map publisher that is actually useful for loading VRT .etc - I am not sure if I understand the VRT loading, since it seems like it is mounted locally onto your system. (under resources?). What would be the path to creating a demonstration of dynamically loading small map tiles as an entity(vehicle) navigates through terrain? Is there a way to directly communicate with the server?
gdal_dataset_color_path: "resources/sargans_color.tif" | ||
max_map_width: 3601 | ||
max_map_height: 3601 | ||
map_origin_latitude: 47.033333 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we want to declare this not from the file but externally? Is this maybe because the map alignment was not correct before #36 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed to declare it somewhere and wanted to provide a reasonable default. Another approach would be to have them as launch arguments. Once we add capability to dynamically load based on UAV location, then this can be removed.
assert(geoTransform.at(4) == 0); // assume no rotation | ||
|
||
return {(geoCoords.x() - geoTransform.at(0)) / geoTransform.at(1), | ||
(geoCoords.y() - geoTransform.at(3)) / geoTransform.at(5)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure whether we want to be able to freely choose geoCoords within the grid_map_geo
framework. At least for me, this additional freedom creates confusion. Wouldn't it be better that we utilize tfs that are clearly defined, so that people doing out of frame stuff can reference the tfs directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is currently used when a user loads a large VRT, and wants to set the map origin in geo coordinates. Could you give me a little more detail on how one can set the map origin using TF?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The map is always placed at (0, 0, 0) and the tf specifies how that frame_id is placed in the datum (e.g. CH1903). This way the map is aligned automatically through tfs, and we don't need to worry where the rviz is looking at.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are dynamically setting the map from the launch file, and eventually loading tiles dynamically, will (0, 0, 0) be where the first map was loaded?
If there's a way to do it in TF, I am interested. The use case I'm trying to support here is user-provided origin anywhere on the SRTM dataset in lat-lon coordinates; the origins of the SRTM tiles are not something the users need to care about because GDAL opens datasets it needs under the hood automatically.
0609689
to
c084630
Compare
Thanks for the detailed review and ideas!
Yea, this sounds like a good idea. Any recommendations?
I adjusted the defaults to allow infinite size, but the params for max map size can still be overridden at launch time, which is necessary for the SRTM1 VRT.
Yes, I can split it up if you like. There will be some code duplication; hope that's ok.
Fixed, all the examples use the file on the server now. |
In principle, you should not need to do anything, as long as the tf is published with the correct datum: e.g. grid_map_geo/src/test_tif_loader.cpp Lines 76 to 90 in 02189d6
The only problem is that the SRTM DEMs are represented in WGS84, but ROS coordiantes are orthograpthic(e.g. ENU). We can probably ignore the distortion for now and represent everything in WGS 84(e.g. x=46.0 means 46.0 degrees in longitude). Long term we should probably reproject this into UTM to be useful for actual fusion with other map representations.
Great!
Sounds good. Since I don't really use the
Awesome, I can try and write a simple application where the map is dynamically spawned around the vehicle position. Although I am not sure what we can do with the map projection problems mentioned in the first point. @Ryanf55 any ideas? |
double mapcenter_n = originY + pixelSizeY * height * 0.5; | ||
maporigin_.espg = ESPG::CH1903_LV03; | ||
maporigin_.position = Eigen::Vector3d(mapcenter_e, mapcenter_n, 0.0); | ||
if (std::isnan(maporigin_.position.x()) || std::isnan(maporigin_.position.y())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would just ignore the actual origin of the map, right? Wouldn't it be better to take whatever is specified in the map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the SRTM1 data file, the map origin is latitude=0, longitude=0, and it's in the middle of the ocean and there is no data available. So yes, if the user does not specify a reasonable origin over land, then it will try loading tiles over the ocean which are entirely void data.
For now, I was just hoping you can launch in a non-hard-coded location (it's in the ROS params). In a future PR, I was planning to add more intelligent handling of where to launch the origin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it actually work when we are trying query specific regions of the VRT? Shouldn't we get the origin of the parsed datum when the smaller terrain file is downloaded? The way tif loading works is that you never need to specify where the origin is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The advantage of using a large VRT is the actual raster tile sizes and origins become data details; it's up to the user to use application-specifics heuristics for setting the origin. For most UAV applications, basing on the current UAV location should work ok.
@Ryanf55 Any updates regarding this direction? |
Sorry for the delay. Busy time at work and little time for FOSS. I've done a quick rebase and squash. Let me know what you would like with the launch files, and I'll get those cleaned up. The map publisher and tif loader are now separate. |
9542a54
to
c665858
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks!
I think we can iterate on how we want to enable the rolling spawning of maps then we will see what the best API would look like
* Add limits for max map size * And instructions for debugging with gdb * GDAL segfaults in RasterIo() with too large of a dataset unless limits are added * Use vsizip to reduce file size * Add map centering * Needs more transform utilities * Switch to std::array instead of raw double array * Add ROS params for setting map origin * Set RasterIo origin in pixel space based on user supplied geo origin * Switch to GdalDatasetUniquePtr * Remove compile warnings * Add launch files Signed-off-by: Ryan Friedman <ryanfriedman5410+github@gmail.com>
c665858
to
b8c0d1e
Compare
Remaining tasks I'd like before merge if you aren't in a rush
Tests I've done so farmap_publisher with ros2 run --prefix 'gdb -ex run --args' grid_map_geo map_publisher --ros-args -p gdal_dataset_path:=/vsizip/vsicurl/https://terrain.ardupilo
t.org/SRTM1/ap_srtm1.zip -p max_map_width:=4096 -p max_map_height:=4096 map_publisher VRT with
TIF loader (single)
TIF loader (multiple):
|
@Ryanf55 I have started looking into implementing a rolling query depending on vehicle position. What I learned in between though is that ROS 2 is not really usable in the field over LTE with large messages (elevation maps/images). It seems to be a known issue without a clear solution. Something we need to keep in mind before people use this package in the field |
@@ -0,0 +1,8 @@ | |||
map_publisher: | |||
ros__parameters: | |||
gdal_dataset_path: /vsizip/vsicurl/https://terrain.ardupilot.org/SRTM1/N09E047.hgt.zip/N09E047.hgt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does the /vsizip/vsicurl
come from?
I tried to directly query the terrain server with gdalinfo, but didn't work:
$ gdalinfo https://terrain.ardupilot.org/SRTM1/N09E047.hgt.zip/N09E047.hgt
ERROR 1: An error occurred while creating a virtual connection to the DAP server:Error while reading the URL: https://terrain.ardupilot.org/SRTM1/N09E047.hgt.zip/N09E047.hgt.ver.
The OPeNDAP server returned the following message:
Not Found: The data source or server could not be found.
Often this means that the OPeNDAP server is missing or needs attention.
Please contact the server administrator.
gdalinfo failed - unable to open 'https://terrain.ardupilot.org/SRTM1/N09E047.hgt.zip/N09E047.hgt'.
Signed-off-by: Ryan Friedman <25047695+Ryanf55@users.noreply.github.com>
background
This PR adds support for loading terrain from the ArduPilot terrain server. I've manually generated the VRT dataset that refers to all the tiles. It's a massive dataset, and if you try loading it on
ros2
branch, it will cause a runtime memory allocation failure crash from trying to read 4TB from the GDAL dataset.To fix it, I added ROS-configurable limits on the grid map size, and set them to reasonable defaults such that none of the other tif files in your
terrain-models/models/*.tif
have problems.Next, in order for the user to set the map origin instead of assuming it's at the center of the dataset, I've added ROS params to set the origin in WGS-84 lat-lon. The vrt launch file
runs the ArduPilot vrt dataset with an origin at CMAC, a popular flying field for ArduPilot SITL.
Due to the increased flexibility of loading terrain, additional protections needed to be added. Through some forward and reverse geo transforms, the user-configured origin is validated to be inside of the raster dataset bounds.
To preserve existing behavior, the configured origin defaults to NaN, and falls back to the assumption that the origin will be at the center of the dataset.
other improvements
I've also done some drive-by improvements such as
gdal_dataset
since that's whats more accurately supportedrelated
This relates to #35, because it allows using a large DEM. It doesn't yet support dynamically moving the grid. This needs to be exposed via params or a ROS service.
follow up
assumptions