Skip to content

Commit 25dafd1

Browse files
committed
Incrementally loading terrain from VRT server (#63)
* Add vrt parsing node * Load position and extent from VRT server F * Add terrain loader node Use gdal transforms Remove geoconversion library F F * Update readme
1 parent 02189d6 commit 25dafd1

File tree

6 files changed

+424
-0
lines changed

6 files changed

+424
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,12 @@ source install/setup.bash
7272
ros2 launch grid_map_geo load_tif_launch.xml
7373
```
7474

75+
76+
## Loading teerrain from a VRT server
77+
78+
One can load a DEM from a terrain server directly.
79+
```
80+
roslaunch grid_map_geo run_terrain_loader.launch
81+
```
82+
83+
![terrain-loader](https://github.com/ethz-asl/grid_map_geo/assets/5248102/e93b2c86-c26a-477c-8704-dc0233b7ef2e)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<launch>
2+
<arg name="visualization" default="true"/>
3+
<arg name="location" default="hinwil"/>
4+
5+
<node pkg="grid_map_geo" type="terrain_loader" name="terrain_loader" output="screen">
6+
<!-- <param name="terrain_path" value="$(find terrain_models)/models/$(arg location).tif"/> -->
7+
<param name="terrain_path" value="/vsizip/vsicurl/https://terrain.ardupilot.org/SRTM1/ap_srtm1.zip/ap_srtm1.vrt"/>
8+
</node>
9+
10+
<group if="$(arg visualization)">
11+
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find grid_map_geo)/launch/terrain_loader.rviz" output="screen"/>
12+
</group>
13+
</launch>
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
Panels:
2+
- Class: rviz/Displays
3+
Help Height: 78
4+
Name: Displays
5+
Property Tree Widget:
6+
Expanded:
7+
- /Global Options1
8+
- /Grid1
9+
- /GridMap1
10+
Splitter Ratio: 0.5
11+
Tree Height: 850
12+
- Class: rviz/Selection
13+
Name: Selection
14+
- Class: rviz/Tool Properties
15+
Expanded:
16+
- /2D Pose Estimate1
17+
- /2D Nav Goal1
18+
- /Publish Point1
19+
Name: Tool Properties
20+
Splitter Ratio: 0.5886790156364441
21+
- Class: rviz/Views
22+
Expanded:
23+
- /Current View1
24+
Name: Views
25+
Splitter Ratio: 0.5
26+
- Class: rviz/Time
27+
Name: Time
28+
SyncMode: 0
29+
SyncSource: ""
30+
- Class: rviz_plugin_tutorials/Teleop
31+
Name: Teleop
32+
Topic: ""
33+
- Class: mav_planning_rviz/PlanningPanel
34+
Name: PlanningPanel
35+
namespace: ""
36+
odometry_topic: ""
37+
planner_name: sertig
38+
planning_budget: 4
39+
Preferences:
40+
PromptSaveOnExit: true
41+
Toolbars:
42+
toolButtonStyle: 2
43+
Visualization Manager:
44+
Class: ""
45+
Displays:
46+
- Alpha: 0.5
47+
Cell Size: 1000
48+
Class: rviz/Grid
49+
Color: 160; 160; 164
50+
Enabled: true
51+
Line Style:
52+
Line Width: 0.029999999329447746
53+
Value: Lines
54+
Name: Grid
55+
Normal Cell Count: 0
56+
Offset:
57+
X: 0
58+
Y: 0
59+
Z: 0
60+
Plane: XY
61+
Plane Cell Count: 10
62+
Reference Frame: map
63+
Value: true
64+
- Alpha: 0.25
65+
Autocompute Intensity Bounds: false
66+
Class: grid_map_rviz_plugin/GridMap
67+
Color: 200; 200; 200
68+
Color Layer: elevation
69+
Color Transformer: IntensityLayer
70+
Enabled: true
71+
Height Layer: elevation
72+
Height Transformer: Layer
73+
History Length: 5
74+
Invert Rainbow: false
75+
Max Color: 255; 255; 255
76+
Max Intensity: 2200
77+
Min Color: 0; 0; 0
78+
Min Intensity: 1400
79+
Name: GridMap
80+
Show Grid Lines: false
81+
Topic: /grid_map
82+
Unreliable: false
83+
Use Rainbow: true
84+
Value: true
85+
Enabled: true
86+
Global Options:
87+
Background Color: 255; 255; 255
88+
Default Light: true
89+
Fixed Frame: map
90+
Frame Rate: 30
91+
Name: root
92+
Tools:
93+
- Class: rviz/Interact
94+
Hide Inactive Objects: true
95+
- Class: rviz/MoveCamera
96+
- Class: rviz/Select
97+
- Class: rviz/FocusCamera
98+
- Class: rviz/Measure
99+
- Class: rviz/SetInitialPose
100+
Theta std deviation: 0.2617993950843811
101+
Topic: /initialpose
102+
X std deviation: 0.5
103+
Y std deviation: 0.5
104+
- Class: rviz/SetGoal
105+
Topic: /move_base_simple/goal
106+
- Class: rviz/PublishPoint
107+
Single click: true
108+
Topic: /clicked_point
109+
Value: true
110+
Views:
111+
Current:
112+
Class: rviz/Orbit
113+
Distance: 30173.89453125
114+
Enable Stereo Rendering:
115+
Stereo Eye Separation: 0.05999999865889549
116+
Stereo Focal Distance: 1
117+
Swap Stereo Eyes: false
118+
Value: false
119+
Field of View: 0.7853981852531433
120+
Focal Point:
121+
X: 5063.75927734375
122+
Y: 2195.057373046875
123+
Z: 3253.49755859375
124+
Focal Shape Fixed Size: true
125+
Focal Shape Size: 0.05000000074505806
126+
Invert Z Axis: false
127+
Name: Current View
128+
Near Clip Distance: 0.009999999776482582
129+
Pitch: 0.639797031879425
130+
Target Frame: map
131+
Yaw: 5.113188743591309
132+
Saved: ~
133+
Window Geometry:
134+
Displays:
135+
collapsed: false
136+
Height: 1136
137+
Hide Left Dock: false
138+
Hide Right Dock: true
139+
PlanningPanel:
140+
collapsed: false
141+
QMainWindow State: 000000ff00000000fd000000040000000000000247000003dbfc020000000bfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000007a000003db000000c700fffffffb0000001a0050006c0061006e006e0069006e006700500061006e0065006c0000000255000000ef0000006e00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d006100670065010000020c000001b10000000000000000fb0000000c00540065006c0065006f00700000000368000000b20000004500ffffff000000010000010f000002cafc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000007a000002ca000000a000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b20000000000000000000000020000073800000039fc0100000002fb0000000800540069006d00650100000000000007380000030700fffffffb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000014efc0100000001fb0000000800540069006d00650100000000000004500000000000000000000004eb000003db00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
142+
Selection:
143+
collapsed: false
144+
Teleop:
145+
collapsed: false
146+
Time:
147+
collapsed: false
148+
Tool Properties:
149+
collapsed: false
150+
Views:
151+
collapsed: true
152+
Width: 1848
153+
X: 72
154+
Y: 27
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/****************************************************************************
2+
*
3+
* Copyright (c) 2021 Jaeyoung Lim. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in
13+
* the documentation and/or other materials provided with the
14+
* distribution.
15+
* 3. Neither the name PX4 nor the names of its contributors may be
16+
* used to endorse or promote products derived from this software
17+
* without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30+
* POSSIBILITY OF SUCH DAMAGE.
31+
*
32+
****************************************************************************/
33+
/**
34+
* @brief Node to test planner in the view utiltiy map
35+
*
36+
*
37+
* @author Jaeyoung Lim <[email protected]>
38+
*/
39+
40+
#include <grid_map_geo/grid_map_geo.h>
41+
#include <grid_map_msgs/GridMap.h>
42+
#include <ros/ros.h>
43+
#include <grid_map_ros/GridMapRosConverter.hpp>
44+
45+
#include <gdal/ogr_spatialref.h>
46+
47+
constexpr int ESPG_WGS84 = 4326;
48+
constexpr int ESPG_CH1903_LV03 = 21781;
49+
50+
void transformCoordinates(int src_coord, const double &x, const double &y, const double &z, int tgt_coord, double &x_t,
51+
double &y_t, double &z_t) {
52+
OGRSpatialReference source, target;
53+
source.importFromEPSG(src_coord);
54+
target.importFromEPSG(tgt_coord);
55+
56+
OGRPoint p;
57+
p.setX(x);
58+
p.setY(y);
59+
p.setZ(z);
60+
p.assignSpatialReference(&source);
61+
62+
p.transformTo(&target);
63+
x_t = p.getX();
64+
y_t = p.getY();
65+
z_t = p.getZ();
66+
return;
67+
}
68+
69+
void LoadTerrainFromVrt(std::string path, const Eigen::Vector3d &query_position, const Eigen::Vector2d &offset,
70+
grid_map::GridMap &map, grid_map::GridMap &vrt_map_object) {
71+
std::shared_ptr<GridMapGeo> vrt_map = std::make_shared<GridMapGeo>();
72+
73+
Eigen::Vector3d query_position_lv03 = query_position;
74+
/// Convert LV03 to WGS84
75+
Eigen::Vector3d map_center_wgs84; // Map center in WGS84
76+
transformCoordinates(ESPG_CH1903_LV03, query_position_lv03(0), query_position_lv03(1), query_position_lv03(2),
77+
ESPG_WGS84, map_center_wgs84.x(), map_center_wgs84.y(), map_center_wgs84.z());
78+
79+
std::cout << "Loading VRT Map:" << std::endl;
80+
std::cout << " - map_center_wgs84:" << map_center_wgs84.transpose() << std::endl;
81+
/// TODO: Discover extent from corners
82+
Eigen::Vector2d extent_wgs84(0.5, 0.5);
83+
vrt_map->initializeFromVrt(path, map_center_wgs84.head(2), extent_wgs84);
84+
std::cout << " - Success!" << std::endl;
85+
86+
/// TODO: Loaded VRT map
87+
std::cout << "Reprojecting map" << std::endl;
88+
Eigen::Vector2d extent_lv03(12000.0, 12000.0);
89+
double resolution{100.0};
90+
Eigen::Vector2d position{Eigen::Vector2d::Zero()};
91+
map.setGeometry(extent_lv03, resolution, position);
92+
map.add("elevation");
93+
map.setFrameId("map");
94+
for (grid_map::GridMapIterator iterator(map); !iterator.isPastEnd(); ++iterator) {
95+
const grid_map::Index index = *iterator;
96+
Eigen::Vector2d cell_position; // Position of cell relative to map coordinates
97+
map.getPosition(index, cell_position);
98+
auto cell_position_lv03 = cell_position + query_position_lv03.head(2); // Position of cell in CH1903/LV03
99+
double dummy;
100+
Eigen::Vector2d cell_position_wgs84;
101+
transformCoordinates(ESPG_CH1903_LV03, cell_position_lv03(0), cell_position_lv03(1), cell_position_lv03(2),
102+
ESPG_WGS84, cell_position_wgs84.x(), cell_position_wgs84.y(), dummy);
103+
// std::cout << " - cell_position_wgs84:" << cell_position_wgs84.transpose() << std::endl;
104+
105+
Eigen::Vector2d local_wgs84 = cell_position_wgs84 - map_center_wgs84.head(2);
106+
double tmp = local_wgs84(0);
107+
local_wgs84(0) = local_wgs84(1);
108+
local_wgs84(1) = tmp;
109+
// std::cout << " - local_wgs84:" << local_wgs84.transpose() << std::endl;
110+
auto elevation = vrt_map->getGridMap().atPosition("elevation", local_wgs84);
111+
map.atPosition("elevation", cell_position) = elevation;
112+
}
113+
map.setPosition(offset);
114+
vrt_map_object = vrt_map->getGridMap();
115+
}
116+
117+
int main(int argc, char **argv) {
118+
ros::init(argc, argv, "terrain_loader");
119+
ros::NodeHandle nh("");
120+
ros::NodeHandle nh_private("~");
121+
122+
ros::Publisher map_pub = nh.advertise<grid_map_msgs::GridMap>("grid_map", 1, true);
123+
ros::Publisher map_pub2 = nh.advertise<grid_map_msgs::GridMap>("grid_map2", 1, true);
124+
125+
std::string path;
126+
nh_private.param<std::string>("terrain_path", path, "resources/cadastre.tif");
127+
128+
Eigen::Vector3d test_position = Eigen::Vector3d(783199.15, 187585.10, 0.0);
129+
130+
for (int i = 0; i < 4; i++) {
131+
Eigen::Vector3d offset = static_cast<double>(i) * Eigen::Vector3d(2500.0, 2500.0, 0.0);
132+
Eigen::Vector3d query_position = test_position + offset;
133+
134+
grid_map::GridMap map;
135+
grid_map::GridMap vrt_map;
136+
LoadTerrainFromVrt(path, query_position, offset.head(2), map, vrt_map);
137+
std::cout << "i: " << i << " offset: " << offset.transpose() << std::endl;
138+
139+
grid_map_msgs::GridMap msg;
140+
grid_map::GridMapRosConverter::toMessage(map, msg);
141+
map_pub.publish(msg);
142+
143+
grid_map_msgs::GridMap msg2;
144+
grid_map::GridMapRosConverter::toMessage(vrt_map, msg2);
145+
map_pub2.publish(msg2);
146+
}
147+
148+
ros::spin();
149+
return 0;
150+
}

include/grid_map_geo/grid_map_geo.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class GridMapGeo {
117117
*/
118118
bool initializeFromGeotiff(const std::string& path);
119119

120+
bool initializeFromVrt(const std::string& path, const Eigen::Vector2d& map_center, Eigen::Vector2d& extent);
121+
120122
/**
121123
* @brief Load a color layer from a geotiff file (orthomosaic)
122124
*

0 commit comments

Comments
 (0)