Fixes terrain origin computing in the inverted pyramid slope terrain#4470
Fixes terrain origin computing in the inverted pyramid slope terrain#4470luoye2333 wants to merge 1 commit intoisaac-sim:mainfrom
Conversation
Greptile OverviewGreptile SummaryFixes terrain origin calculation for inverted pyramid slope terrain by introducing a configurable Key Changes:
Issues Found:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant pyramid_sloped_terrain
participant height_field_to_mesh_v2
participant convert_height_field_to_mesh
User->>pyramid_sloped_terrain: Call with difficulty, cfg
Note over pyramid_sloped_terrain: Decorated with @height_field_to_mesh_v2(terrain_origin_judge_width=1.0)
pyramid_sloped_terrain->>height_field_to_mesh_v2: Execute decorator wrapper
height_field_to_mesh_v2->>height_field_to_mesh_v2: Validate border_width
height_field_to_mesh_v2->>height_field_to_mesh_v2: Allocate height field buffer with border
height_field_to_mesh_v2->>pyramid_sloped_terrain: Call original function with adjusted cfg
pyramid_sloped_terrain-->>height_field_to_mesh_v2: Return height field array (z_gen)
height_field_to_mesh_v2->>convert_height_field_to_mesh: Convert heights to mesh
convert_height_field_to_mesh-->>height_field_to_mesh_v2: Return vertices, triangles
height_field_to_mesh_v2->>height_field_to_mesh_v2: Compute origin using terrain_origin_judge_width=1.0
Note over height_field_to_mesh_v2: Uses 1.0m square area instead of default 2.0m<br/>to avoid sampling outside platform in inverted pyramid
height_field_to_mesh_v2-->>User: Return [mesh], origin
|
| def height_field_to_mesh_v2(terrain_origin_judge_width: float = 2.0): | ||
| """ | ||
| the terrain origin is computed as the max in the square area around the center of the terrain, | ||
| the square width is `terrain_origin_judge_width` | ||
| """ |
There was a problem hiding this comment.
docstring doesn't follow the same format as height_field_to_mesh. Should include Args, Returns sections and proper capitalization/punctuation
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| x1 = int((cfg.size[0] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| x2 = int((cfg.size[0] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| y1 = int((cfg.size[1] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| y2 = int((cfg.size[1] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| origin_z = np.max(heights[x1:x2, y1:y2]) * cfg.vertical_scale |
There was a problem hiding this comment.
potential index out of bounds if terrain_origin_judge_width is larger than the terrain size. Consider adding validation
| x1 = int((cfg.size[0] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| x2 = int((cfg.size[0] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| y1 = int((cfg.size[1] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| y2 = int((cfg.size[1] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| origin_z = np.max(heights[x1:x2, y1:y2]) * cfg.vertical_scale | |
| # compute origin | |
| if terrain_origin_judge_width > min(cfg.size[0], cfg.size[1]): | |
| raise ValueError( | |
| f"The terrain origin judge width ({terrain_origin_judge_width}) must be smaller than " | |
| f"the minimum terrain size ({min(cfg.size[0], cfg.size[1])})." | |
| ) | |
| x1 = int((cfg.size[0] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| x2 = int((cfg.size[0] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| y1 = int((cfg.size[1] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | |
| y2 = int((cfg.size[1] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) |
| x2 = int((cfg.size[0] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| y1 = int((cfg.size[1] * 0.5 - terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| y2 = int((cfg.size[1] * 0.5 + terrain_origin_judge_width / 2.0) / cfg.horizontal_scale) | ||
| origin_z = np.max(heights[x1:x2, y1:y2]) * cfg.vertical_scale |
There was a problem hiding this comment.
if x1 >= x2 or y1 >= y2 due to rounding, np.max(heights[x1:x2, y1:y2]) will fail. Check that indices form valid slices
| @@ -77,6 +76,59 @@ def wrapper(difficulty: float, cfg: HfTerrainBaseCfg): | |||
| return wrapper | |||
|
|
|||
|
|
|||
| def height_field_to_mesh_v2(terrain_origin_judge_width: float = 2.0): | |||
There was a problem hiding this comment.
Hi, thank you for sharing the bug and potential fix.
This parameter terrain_origin_judge_width seems to depend a lot on the choice of the platform width size. I don't think hard-coding it here like this is the right solution.
The proper solution should be that the height-field generator also returns the origin. Then all this hard-coding logic inside height_field_to_mesh can be avoided.
2ef7fc8 to
f3061a4
Compare
Description
In
height_field_to_meshfunction, the terrain origin is computed as the max in the square area around the center of the terrain,and the square has a fixed width of 2 meters.
In inverted pyramid slope terrain, the default
platform_widthis1.0meter. Therefore the area outside the platform is also calculated in thenp.maxfunction. This caused the terrain origin to be a little higher than the ground. See theScreenshotsbelow. Non-inverted pyramid terrain do not have this problem because the function ismax.To fix, a param
terrain_origin_judge_widthis added to theheight_field_to_meshwrapper (default is 2.0 so the behaviour is same as before) and we can use decorator@height_field_to_mesh_v2(terrain_origin_judge_width=1.0)to change themaxfunction area. For the default platform 1.0 meter in inverted pyramid slope terrain, a half widthterrain_origin_judge_width=1.0is ok.Type of change
Screenshots
Please attach before and after screenshots of the change if applicable.
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there