Skip to content

Commit 1010635

Browse files
committed
Added page in docs for lunar sim instructions (#44).
The demonstrations now include a lunar simulation. This commit adds a documentation page to the website describing how the simulation can be built and run.
1 parent 0ad2383 commit 1010635

File tree

7 files changed

+346
-0
lines changed

7 files changed

+346
-0
lines changed

source/Demos.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ There are currently two Space ROS demonstration applications.
55
The first demo uses `MoveIt2 <https://moveit.ros.org/>`_ and a model of the `Canadarm manipulator <https://en.wikipedia.org/wiki/Canadarm>`_ along with the Space ROS base image.
66
In this demo, MoveIt2 is used to plan the motion for the Canadarm, which is running in simulation.
77
The second demo shows the `Mars Curiosity rover <https://mars.nasa.gov/msl/home/>`_ in simulation, presenting multiple ROS 2 services to allow the user to directly control the rover.
8+
The third demo is a lunar world simulation with realistic terrain and lighting as well as an open-source lunar rover model.
89
The following pages go into detail to show you how to run these demo applications.
910

1011
.. toctree::
@@ -13,3 +14,4 @@ The following pages go into detail to show you how to run these demo application
1314

1415
Demos/Canadarm
1516
Demos/Mars-Rover
17+
Demos/LunarSim

source/Demos/LunarSim.rst

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
LunarSim Demo
2+
==============
3+
4+
Space ROS Lunar Sim Demo Docker Image
5+
-------------------------------------
6+
7+
The Space ROS Lunar Sim Demo docker image uses the spaceros docker image (*osrf/space-ros:latest*) as its base image.
8+
The Dockerfile installs all of the prerequisite system dependencies along with the demo source code, then builds the Space ROS Lunar Sim Demo.
9+
10+
This demo includes a Gazebo simulation of the lunar environment (specfically around the Shackleton crater near the south pole). It uses
11+
Digital Elevation Models (DEMs) from the Lunar Orbiter Laser Altimeter (LOLA) to accurately simulate the lunar surface in a specific region. It also contains a dynamic model of the Sun that moves according to Ephemeris data.
12+
13+
Building the Demo Docker
14+
^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
The demo image builds on top of the spaceros image.
17+
To build the docker image, first ensure the spaceros base image is available either by `building it locally <https://github.com/space-ros/space-ros>`_ or pulling it.
18+
19+
Then build lunar_sim demo images:
20+
21+
.. code-block:: bash
22+
23+
cd lunarsim_demo
24+
./build.sh
25+
26+
27+
Running the Demo Docker
28+
^^^^^^^^^^^^^^^^^^^^^^^
29+
30+
Run the following to allow GUI passthrough:
31+
32+
.. code-block:: bash
33+
34+
xhost +local:docker
35+
36+
37+
Then run:
38+
39+
.. code-block:: bash
40+
41+
./run.sh
42+
43+
Depending on the host computer, you might need to remove the ``--gpus all`` flag in ``run.sh``, which uses your GPUs.
44+
45+
46+
Running the Demo
47+
^^^^^^^^^^^^^^^^
48+
49+
Once the container is running, you can launch the demo by running:
50+
51+
.. code-block:: bash
52+
53+
souce install/setup.bash
54+
ros2 launch lunar_sim_gz_worlds lunar_sim.launch
55+
56+
This will launch the gazebo lunar world, spawn the rover and start teleop in a new terminal window which enables you to control the rover as per the instructions in the terminal window.
57+
58+
59+
Changing the Digital Elevation Model (DEM)
60+
------------------------------------------
61+
62+
The variation in elevation of the Lunar surface within the simulation
63+
environment is generated using a `Digital Elevation Model
64+
(DEM) <https://en.wikipedia.org/wiki/Digital_elevation_model>`_, also
65+
called a Heightmap, which is a 2D representation of the elevation of a
66+
terrain. These are usually available in PNG or TIF format, where the
67+
value of each pixel represents the elevation.
68+
69+
In this tutorial we will use the Shoemaker_final_adj_5mpp_surf.tif from
70+
`High-Resolution LOLA Topography for Lunar South Pole
71+
Sites <https://pgda.gsfc.nasa.gov/products/78>`_.
72+
73+
Gazebo using ogre2 as the render engine requires that height maps have a
74+
size of 2^n x 2^n. In our case the Shoemaker_final_adj_5mpp_surf.tif
75+
image is 4000x4000 which doesn’t meet this requirement, so we can either
76+
downscale it using a library called gdal in order to load the whole
77+
terrain, or crop it using the tool crop_dem.py script to use a part of
78+
the terrain and preserve the resolution. Reducing the size of the DEM
79+
will also make it quicker to render by Gazebo.
80+
81+
Downscaling
82+
^^^^^^^^^^^
83+
gdal can be installed using the commands below:
84+
85+
.. code:: bash
86+
87+
sudo add-apt-repository ppa:ubuntugis/ppa
88+
sudo apt-get update
89+
sudo apt-get install gdal-bin
90+
sudo apt-get install libgdal-dev
91+
92+
We can then use the gdalwarp tool to downsample to 2048x2048, which
93+
meets the 2^n x 2^n requirement:
94+
95+
.. code:: bash
96+
97+
gdalwarp -ts 2048 2048 Shoemaker_final_adj_5mpp_surf.tif Shoemaker_final_adj_5mpp_surf_2048.tif
98+
99+
Cropping
100+
^^^^^^^^
101+
102+
The crop_dem.py script, located in lunarsim_gz_worlds/scrikpts, can be
103+
used to crop a part of the DEM out:
104+
105+
.. code:: bash
106+
107+
python3 crop_dem.py Shoemaker_final_adj_5mpp_surf.tif Shoemaker_final_adj_5mpp_surf_1k.tif 1872 1872 256
108+
109+
Creating Normal Map
110+
^^^^^^^^^^^^^^^^^^^
111+
112+
A normal map is a 2D texture that encodes information about the surface
113+
orientation (normals) of the terrain, which influences how light
114+
interacts with the surface. We can derive this texture by calculating
115+
the gradients within our DEM. This can be done using the
116+
surface_normals.py script in lunarsim_gz_worlds/scripts:
117+
118+
.. code:: bash
119+
120+
python3 surface_normals.py
121+
122+
The image created will look something like this:
123+
124+
.. image:: /images/lunar_normal_map.png
125+
126+
.. rst-class:: image-subtitle
127+
128+
Normal map generated from the DEM
129+
130+
Blending Normals
131+
^^^^^^^^^^^^^^^^
132+
The normal map we generated can be blended with a higher resolution texture
133+
in order to create a more accurate representation of what the surface
134+
would look like at a smaller scale. Sample higher resolution textures
135+
can be downloaded at `Polyhaven <https://polyhaven.com/>`_. For
136+
instance, the normal map from `this sand
137+
texture <https://polyhaven.com/a/sandy_gravel>`_ can be blended with
138+
DEM’s normal map. This can be done using the blend_normals.py script
139+
located in lunarsim_gz_worlds/scripts:
140+
141+
.. code:: bash
142+
143+
python3 blend_normals.py Shoemaker_final_adj_5mpp_surf_2048_normals.png sandy_gravel_nor_gl_4k.exr Shoemaker_sandy_norms.png
144+
145+
By blending the normal map from the DEM with the sandy texture normal
146+
map, we get the following blended map:
147+
148+
.. image:: /images/lunar_textured_normals.png
149+
150+
.. rst-class:: image-subtitle
151+
152+
Surface Normals of the terrain in LunarSim with blended sand texture normals
153+
154+
Using DEM in Gazebo
155+
^^^^^^^^^^^^^^^^^^^
156+
We also need to know the distance that the DEM covers in the x, y and z directions, which we
157+
can do with gdalinfo (requires installation of gdal, instructions in the
158+
Downscaling section):
159+
160+
.. code:: bash
161+
162+
gdalinfo -stats Shoemaker_final_adj_5mpp_surf.tif
163+
164+
The output will contain some useful metadata on the DEM:
165+
166+
.. code:: bash
167+
168+
Data axis to CRS axis mapping: 1,2
169+
Origin = (66000.000000000000000,49000.000000000000000)
170+
Pixel Size = (5.000000000000000,-5.000000000000000)
171+
Metadata:
172+
AREA_OR_POINT=Area
173+
NC_GLOBAL#Conventions=COARDS, CF-1.5
174+
NC_GLOBAL#GMT_version=5.4.5 [64-bit]
175+
NC_GLOBAL#history=xyz2grd -bi3 -I5 -R6.60000000000e+04/8.60000000000e+04/2.90000000000e+04/4.90000000000e+04 -Gtest.grd -r
176+
NC_GLOBAL#node_offset=1
177+
x#actual_range={66000,86000}
178+
x#long_name=x
179+
y#actual_range={29000,49000}
180+
y#long_name=y
181+
z#actual_range={-1075.152099609375,713.5578002929688}
182+
z#long_name=z
183+
z#_FillValue=nan
184+
185+
From this we can ascertain that the resolution is 5m per pixel (which
186+
was also mentioned in the source), as well as get the distances covered
187+
in the x, y and z directions by subtracting the start of the range from
188+
the end. This gives us 20,000 metres in the x (86000 - 66000), 20,000
189+
metres in the y (49000-29000) and 1789 metres (713.6 - (-1075.2)) in the
190+
z.
191+
192+
The DEM can then be utilised within a Gazebo SDF as show below:
193+
194+
.. code:: xml
195+
196+
<link name="link">
197+
<collision name="collision">
198+
<geometry>
199+
<heightmap>
200+
<uri>dem/Shoemaker_final_adj_5mpp_surf_2048.tif</uri>
201+
<size>20000 20000 1789</size>
202+
<pos>0 0 0</pos>
203+
</heightmap>
204+
</geometry>
205+
</collision>
206+
<visual name="visual">
207+
<geometry>
208+
<heightmap>
209+
<use_terrain_paging>false</use_terrain_paging>
210+
<texture>
211+
<diffuse>materials/textures/TerrainNew_Albedo.jpg</diffuse>
212+
<normal>materials/textures/Shoemaker_final_adj_5mpp_surf_2048_normals.png</normal>
213+
<size>20000 20000 1789</size>
214+
</texture>
215+
<uri>dem/Shoemaker_final_adj_5mpp_surf_2048.tif</uri>
216+
<size>20000 20000 1789</size>
217+
<pos>0 0 0</pos>
218+
</heightmap>
219+
</geometry>
220+
</visual>
221+
</link>
222+
223+
Let’s walk through the xml.
224+
225+
.. code:: xml
226+
227+
<collision name="collision">
228+
<geometry>
229+
230+
This defines that we are creating a collision geometry within the
231+
simulation, which is what allows for interactions between objects and
232+
the surface.
233+
234+
.. code:: xml
235+
236+
<heightmap>
237+
<uri>dem/Shoemaker_final_adj_5mpp_surf_2048.tif</uri>
238+
<size>20000 20000 1789</size>
239+
<pos>0 0 0</pos>
240+
</heightmap>
241+
242+
Here we define our heightmap to be used to create the collision
243+
geometry. The ``uri`` tag specifies where the heightmap file can be
244+
found. The ``size`` tag specifies the dimensions of the Heightmap in
245+
meters along the x, y and z axis. If you want this to scale properly to
246+
the real environment, enter the size as the size of the real area that
247+
the DEM covers, which we derived using gdalinfo. Finally the ``pos``
248+
tag defines the origin of the heightmap.
249+
250+
.. warning::
251+
The Heightmap must be a square, or it will cause issues
252+
where the collision and visual geometries are not aligned. The size
253+
also needs to be a power of 2.
254+
255+
.. code:: xml
256+
257+
<visual name="visual">
258+
<geometry>
259+
260+
Now we’re creating a visual geometry so the rover (and humanoid user)
261+
can see the lunar surface.
262+
263+
.. code:: xml
264+
265+
<heightmap>
266+
<use_terrain_paging>false</use_terrain_paging>
267+
<texture>
268+
<diffuse>materials/textures/TerrainNew_Albedo.jpg</diffuse>
269+
<normal>materials/textures/Shoemaker_final_adj_5mpp_surf_2048_normals.png</normal>
270+
<size>20000 20000 1789</size>
271+
</texture>
272+
<uri>dem/Shoemaker_final_adj_5mpp_surf_2048.tif</uri>
273+
<size>20000 20000 1789</size>
274+
<pos>0 0 0</pos>
275+
</heightmap>
276+
277+
Here again we define a Heightmap so the visual geometry matches the
278+
collision surface. ``uri``, ``size`` and ``pos`` tags should
279+
remain the same. We now also have a ``texture`` tag where we supply an
280+
Albedo map to define what the base color of the surface is , and the
281+
Normal map that we previously generated to define how light interacts
282+
with it. The size of the texture should be the same as the Heightmap
283+
size.
284+
285+
Heightmaps collected from Lunar Reconnaissance Orbiter which surveys the
286+
Lunar South Pole can be found here:
287+
https://astrogeology.usgs.gov/search/map/moon_lro_lola_dem_118m
288+
289+
https://pgda.gsfc.nasa.gov/products/78
290+
291+
https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=4720
292+
293+
Note that while using heightmaps, the default collision detector ode `doesn’t seem to work very
294+
well <https://github.com/gazebosim/gz-sim/issues/1714>`_. So we need to
295+
make sure we are using the bullet detector instead. We can do this by
296+
adding a tag within the sdf file that we’re loading the model into:
297+
298+
.. code:: xml
299+
300+
<physics name="1ms" type="ignored">
301+
<dart>
302+
<!-- Heightmaps behave better with the bullet collision detector -->
303+
<collision_detector>bullet</collision_detector>
304+
</dart>
305+
</physics>
306+
307+
Dynamic Sun Simulation Using Ephemeris Data
308+
-------------------------------------------
309+
Our simulation environment contains a dynamic model of the Sun that moves according to Ephemeris data retrieved using the NASA Horizons tool.
310+
The model is loaded into the world using a Gazebo plugin, which allows for dynamic changes to the models position as well as the attached light source. We use a `pre-existing model <https://app.gazebosim.org/OpenRobotics/fuel/models/Sun>`_ of the Sun to define it's visual appearance. Latitude and longitude of the center of the DEM can be retrieved using this gdalinfo command:
311+
312+
.. code:: bash
313+
314+
gdalinfo -stats Shoemaker_final_adj_5mpp_surf.tif
315+
316+
The output should give us the coordinates of the center of the DEM:
317+
318+
::
319+
320+
Corner Coordinates:
321+
Upper Left ( 66000.000, 49000.000) ( 53d24'32.08"E, 87d17'22.89"S)
322+
Lower Left ( 66000.000, 29000.000) ( 66d16'46.58"E, 87d37'22.65"S)
323+
Upper Right ( 86000.000, 49000.000) ( 60d19'36.90"E, 86d44'12.26"S)
324+
Lower Right ( 86000.000, 29000.000) ( 71d21'55.49"E, 87d 0'27.63"S)
325+
Center ( 76000.000, 39000.000) ( 62d50' 6.05"E, 87d11' 0.65"S)
326+
327+
328+
This information can be used to retrieve the Apparent Azimuth and Elevation of the Sun in the Lunar Sky. `NASA's Horizons System <https://ssd.jpl.nasa.gov/horizons/app.html#>`_ provides an easy to use interface to generate Ephemeris data for a wide range of solar system bodies. In order to get the required data for the plugin, enter the Longitude and Latitude data into the application with the target body as the Sun and Observer location as the Moon:
329+
330+
.. image:: /images/nasa_horizons.png
331+
332+
Then enter in the settings to specify the timesteps as well as selecting the type of data we want (in this case just Azimuth and Elevation):
333+
334+
.. image:: /images/nasa_horizons_settings.png
335+
336+
This should output a table with the required data:
337+
338+
.. image:: /images/nasa_horizons_output.png
339+
340+
This can then be added to a csv file and loaded into the plugin.
341+
342+
In Gazebo, the Sun is represented as an actor, an animated model that follows a predefined trajectory. This trajectory is loaded through a plugin, and both the visual representation of the Sun and its associated light source in the world are updated accordingly.
343+
344+

source/images/lunar_normal_map.png

1.58 MB
Loading
1.91 MB
Loading

source/images/nasa_horizons.png

105 KB
Loading
133 KB
Loading
184 KB
Loading

0 commit comments

Comments
 (0)