-
Notifications
You must be signed in to change notification settings - Fork 41
Dynamic Terrain
The OceanWATERS lander will be taking samples of terrain soil which will slightly change the environment / terrain around the rover after it is done taking these samples. To provide higher fidelity of the simulation, the Dynamic Terrain plugin reflects these changes as they occur at run-time. Updating the world / terrain is typically not featured in the majority of simulation software. For that we extended the functionality of Gazebo – the simulation software for OceanWATERS – to dynamically manipulate the terrain at run-time.
- The IRGLinkTracksPlugin and DynamicTerrainVisual plugin may conflict with each other as both affect the visual appearance of the terrain.
- The DynamicTerrainVisual is also incompatible with the HeightmapLODPlugin; Either disable the plugin or configure it to always use the highest LOD level.
The package is made up of two plugins, namely DynamicTerrainModel (ModelPlugin) and DynamicTerrainVisual (VisualPlugin). The two plugins are typically used together towards a terrain model, although it is possible to use each one separately. Once the plugins are activated you may perform an operation on the terrain by publishing to /ow_dynamic_terrain/modify_terrain_*
topics. Current available topics/operations are:
/ow_dynamic_terrain/modify_terrain_circle
/ow_dynamic_terrain/modify_terrain_ellipse
/ow_dynamic_terrain/modify_terrain_patch
You may perform a circle modify terrain operation by publishing a message as follows:
rostopic pub --once /ow_dynamic_terrain/modify_terrain_circle ow_dynamic_terrain/modify_terrain_circle \
"{position: {x: 0, y: 0, z: 2},
outer_radius: 0.1,
inner_radius: 0.001,
weight: -1.0,
merge_method: 'min' }"
The listing below explains used parameter:
- position: is in reference to gazebo world coordinates The x and y values of the position define the center of the circle The z - if used - would offset all values generated by the modify operation. i.e the generated height value is equivalent to (z + effective_weight).
- outer_radius, inner_radius: The hard limit of the operation, beyond that the operation has no effect. The inner radius is where the provided weight is full realized, beyond the inner radius the weight fades down up to the outer distance. The following figure illustrates the effective weight at any given (x, y) with respect to these radii:
- weight: Depending on the weight sign the operation will either raise or lower the terrain around the provided position (inner_radius may not be larger than outer_radius).
-
merge_method: The merge_method parameter decides how to merge generated values with height values of the terrain; available choices:
- keep: current_height_value is left unchanged
- replace: current_height_value is replaced by generated_height_value
- add: The new height would be the sum of current_height_value and generated_height_value
- sub: The generated_height_value is subtracted from current_height_value
- min: The generated_height_value would replace current_height_value iff generated_height_value < current_height_value
- max: The generated_height_value would replace current_height_value iff generated_height_value > current_height_value
- avg: The new height value would be the average of current_height_value and generated_height_value
- default: If no merge_method is specified then the default merge_method is add.
In the above example, with z value set to 2.0 and weight is -1.0 this would produce a hemisphere with lowest value of 2.0 + (-1.0) = 1.0. Since merged_method is set to 'min', if current height values of the terrain at point (x = 0, y = 0) exceed 1.0 will be replaced by 1.0.
The following images shows how to perform a lower and a raise operations by varying the sign of the weight parameter; in each row of the example we use different value of the outer_radius and inner_radius:
Original |
weight: -1.0 position: {x: 0, y: 0, z: 0} merge_method: add |
weight: +1.0 position: {x: 0, y: 0, z: 0} merge_method: add |
---|---|---|
![]() |
![]() outer_radius: 0.1 inner_radius: 0.001 |
![]() outer_radius: 0.1 inner_radius: 0.001 |
![]() |
![]() outer_radius: 0.1 inner_radius: 0.05 |
![]() outer_radius: 0.1 inner_radius: 0.05 |
![]() |
![]() outer_radius: 0.1 inner_radius: 0.1 |
![]() outer_radius: 0.1 inner_radius: 0.1 |
The following table shows the effect of varying the z value based along with the merge_method:
Original |
merge_method: add outer_radius: 0.1 inner_radius: 0.001 weight: -1.0 |
merge_method: min outer_radius: 0.1 inner_radius: 0.001 weight: -1.0 |
---|---|---|
![]() |
![]() position: {x: 0, y: 0, z: 2} |
![]() position: {x: 0, y: 0, z: 2} |
![]() |
![]() position: {x: 0, y: 0, z: 1} |
![]() position: {x: 0, y: 0, z: 1} |
![]() |
![]() position: {x: 0, y: 0, z: 0} |
![]() position: {x: 0, y: 0, z: 2} |
![]() |
![]() position: {x: 0, y: 0, z: -1} |
![]() position: {x: 0, y: 0, z: -1} |
You may perform a circle modify terrain operation by publishing a message as follows:
rostopic pub --once /ow_dynamic_terrain/modify_terrain_ellipse ow_dynamic_terrain/modify_terrain_ellipse \
"{position: {x: 0, y: 0, z: 2},
orientation: 30.0,
outer_radius_a: 0.2,
outer_radius_b: 0.1,
inner_radius_a: 0.001,
inner_radius_b: 0.001,
weight: -1.0,
merge_method: 'min'}"
The parameters used here are mostly the same as the ones described in "Modify Terrain with Circle" section with the exception of outer_radius_a, outer_radius_b, inner_radius_a, inner_radius_b. These parameters correspond to the two radii of an ellipse (a, b). The weight is applied at 100% within the inner ellipse, 0% outside the outer ellipse, In the distance between the outer ellipse and inner one, the applied weight fades out quadratically.
Additionally, an ellipse can have an orientation parameter (measured in degrees) that would rotate the ellipse around its center. The following table results obtained by varying the orientation:
Original | orientation: 0 | orientation: 45 | orientation: 90 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Results obtained by slightly varying the outer and inner radii:
Original | outer_radius_a: 0.2 outer_radius_b: 0.1 inner_radius_a: 0.001 inner_radius_b: 0.001 |
outer_radius_a: 0.2 outer_radius_b: 0.1 inner_radius_a: 0.05 inner_radius_b: 0.05 |
outer_radius_a: 0.2 outer_radius_b: 0.1 inner_radius_a: 0.1 inner_radius_b: 0.1 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
You may use the provide modify_terrain_patch helper utility to submit a tiff image to modify the terrain as shown in the example below:
roscd ow_dynamic_terrain
rosrun ow_dynamic_terrain modify_terrain_patch_pub.py \
misc/first_pass_heightmap.tif
'The example adds the supplied first_pass_heightmap.tif example to the loaded terrain around the origin point.
The following example applies only the height values of the image that exceeds the current elevation values of the terrain which for the europa demo sets at ~1.5 near the center:
roscd ow_dynamic_terrain
rosrun ow_dynamic_terrain modify_terrain_patch_pub.py \
--position_z 1.5 \
--merge_method max \
misc/first_pass_heightmap.tif
Full options of the modify_terrain_patch_pub program:
rosrun ow_dynamic_terrain modify_terrain_patch_pub.py [-h]
[--position_x POSITION_X]
[--position_y POSITION_Y]
[--position_z POSITION_Z]
[--orientation ORIENTATION]
[--z_scale Z_SCALE]
[--merge_method MERGE_METHOD]
image
The listing below explains used parameter:
- image (required): accepts a path to a valid image file.
- position: maps the center of the image to the terrain, given in gazebo world coordinates.
- orientation: rotate the image around its center; measured in degrees.
- z_scale: a scale factor that will be applied to image intensities. If omitted or zero is specified then the image intensities will be normalized.
- merge_method: decides how to merge the height values of supplied image with the current height values of the terrain. The choices are the same ones listed in the "Modify Terrain with Circle" section.
NOTE: Only single channel 32 float image formats are supported.
Results when using an image and varying the orientation:
Original |
orientation: 0 merge_method: add |
orientation: 45 merge_method: add |
orientation: 90 merge_method: add |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Results obtained by varying (mainly) the merge_method and the z value for first case only:
Original | orientation: 0 position_z: 0 merge_method: add |
orientation: 0 position_z: 1.5 merge_method: min |
orientation: 0 position_z: 1.5 merge_method: max |
orientation: 0 position_z: 1.5 merge_method: avg |
---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
In certain situations it may be desirable to only modify one of the two terrain aspects: the visual part and the physical. This certainly can be achieved by enabling one of the two plugins for the model. However, in other cases the user may want to alter each aspect slightly different than the other. To handle such use case, the two plugins DynamicTerrainVisual and DynamicTerrainModel both add an extension to the three topics listed above that correspond to their aspect. i.e. The DynamicTerrainVisual plugin has the following three additional topics that it subscribes to:
/ow_dynamic_terrain/modify_terrain_circle/visual
/ow_dynamic_terrain/modify_terrain_ellipse/visual
/ow_dynamic_terrain/modify_terrain_patch/visual
Meanwhile, the DynamicTerrainModel plugin adds the following three topics:
/ow_dynamic_terrain/modify_terrain_circle/collision
/ow_dynamic_terrain/modify_terrain_ellipse/collision
/ow_dynamic_terrain/modify_terrain_patch/collision
The DynamicTerrainVisual and DynamicTerrainModel plugins both publish their own topics that provide information on how terrain has been modified each time a modification occurs.
/ow_dynamic_terrain/modification_differential/visual
/ow_dynamic_terrain/modification_differential/collision
These two topics can be used to cause terrain modification to trigger secondary behavior in the simulation, or simply as debug tools. Their message format is defined by ow_dyanmic_terrain/msg/modified_terrain_diff.msg
, and it contains the following.
Field Name | Type | Description |
---|---|---|
diff | sensor_msgs/Image | An image that contains changes in terrain height value as a result of modification. The image is always centered with the terrain brush that caused the modification. |
position | geometry_msgs/Point32 | The position in the world where modification took place. This is the same as the position of the terrain brush. |
height | float32 | The height of the image in world units. |
width | float32 | The width of the image in world units. |
- Terrain updates happen almost instantly but this largely depends on terrain resolution, patch size and the machine used to run the simulation.
- The implementation assumes that the sampling of the heightmap is same for both plugins.
- This has been only test to work with ODE Physics engine. Other physics engine supplied by Gazebo are unlikely to work.
- To make sure that visual changes match with physical updates, terrain smoothing is not invoked after the update. This would only affects the updated region and not the entire terrain.