Skip to content

Commit cd43beb

Browse files
LuigiPenco93calvertdw
authored andcommitted
zed occupancy map fix
1 parent 484fd40 commit cd43beb

File tree

2 files changed

+137
-31
lines changed

2 files changed

+137
-31
lines changed

ihmc-high-level-behaviors/src/libgdx/java/us/ihmc/rdx/perception/RDXZEDOccupancyMapDemo.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import us.ihmc.euclid.tuple3D.Point3D;
66
import us.ihmc.perception.RawImage;
77
import us.ihmc.rdx.Lwjgl3ApplicationAdapter;
8+
import us.ihmc.rdx.RDXPointCloudRenderer;
89
import us.ihmc.rdx.imgui.ImGuiTools;
910
import us.ihmc.rdx.imgui.ImGuiUniqueLabelMap;
11+
import us.ihmc.rdx.sceneManager.RDXSceneLevel;
1012
import us.ihmc.rdx.ui.RDXBaseUI;
1113
import us.ihmc.rdx.ui.graphics.RDXImageVisualizer;
1214
import us.ihmc.rdx.ui.graphics.RDXPerceptionVisualizersPanel;
@@ -16,12 +18,14 @@
1618
import us.ihmc.sensors.zed.ZEDSVOPlaybackSensor;
1719
import us.ihmc.zed.global.zed;
1820

21+
import java.util.List;
22+
1923
/**
2024
* Demo class for ZED occupancy map.
2125
*/
2226
public class RDXZEDOccupancyMapDemo extends Lwjgl3ApplicationAdapter
2327
{
24-
private static final String SVO_FILE = "/home/duncan/Downloads/20251110_162146_H1ZEDXMiniFirstMustardGrab.svo2";
28+
private static final String SVO_FILE = "/home/duncan/Downloads/20251020_ZEDXMini_DoorChargeBarrierBottle.svo2";
2529
private static final RDXBaseUI baseUI = new RDXBaseUI();
2630
private final ZEDSVOPlaybackSensor zedSensor = new ZEDSVOPlaybackSensor(0, ZEDModelData.ZED_2I, zed.SL_DEPTH_MODE_PERFORMANCE, SVO_FILE);
2731
private RDXPerceptionVisualizersPanel visualizers;
@@ -30,6 +34,9 @@ public class RDXZEDOccupancyMapDemo extends Lwjgl3ApplicationAdapter
3034
private final ImGuiUniqueLabelMap labels = new ImGuiUniqueLabelMap(getClass());
3135
private final ImInt requestedPosition = new ImInt();
3236

37+
private RDXPointCloudRenderer occupancyRenderer;
38+
private static final int MAX_POINTS_TO_RENDER = 100000;
39+
3340
@Override
3441
public void create()
3542
{
@@ -47,8 +54,16 @@ public void create()
4754
}
4855
visualizers.create(baseUI);
4956

57+
// Create occupancy renderer from spatial mesh
58+
occupancyRenderer = new RDXPointCloudRenderer();
59+
occupancyRenderer.create(MAX_POINTS_TO_RENDER);
60+
occupancyRenderer.setColoringMethod(RDXPointCloudRenderer.ColoringMethod.GRADIENT_WORLD_Z);
61+
baseUI.getPrimaryScene().addRenderableProvider(occupancyRenderer, RDXSceneLevel.VIRTUAL);
62+
5063
baseUI.getImGuiPanelManager().addPanel("Demo", this::renderImGuiWidgets);
5164

65+
zedSensor.enablePositionalTracking(true);
66+
zedSensor.enableSpatialMapping(true);
5267
zedSensor.startSensor();
5368
zedSensor.getGrabThread().setFrequencyLimit(15.0);
5469
}
@@ -91,11 +106,55 @@ public void render()
91106
image.release();
92107
}
93108
}
109+
updateOccupancyPointCloud();
94110

95111
baseUI.renderBeforeOnScreenUI();
96112
baseUI.renderEnd();
97113
}
98114

115+
private void updateOccupancyPointCloud()
116+
{
117+
if (occupancyRenderer == null)
118+
return;
119+
120+
float[] vertices = zedSensor.getMeshVertices();
121+
int numVertices = zedSensor.getMeshNumVertices();
122+
123+
if (vertices == null || numVertices == 0)
124+
{
125+
occupancyRenderer.updateMesh(List.of());
126+
return;
127+
}
128+
129+
// CRITICAL: Enforce strict limit - never exceed MAX_POINTS_TO_RENDER
130+
int pointsToSample = Math.min(numVertices, MAX_POINTS_TO_RENDER);
131+
// Calculate stride to hit exactly MAX_POINTS_TO_RENDER points
132+
int stride = numVertices > MAX_POINTS_TO_RENDER ?
133+
(numVertices + MAX_POINTS_TO_RENDER - 1) / MAX_POINTS_TO_RENDER : 1;
134+
// Pre-allocate exactly the number we'll use
135+
Point3D[] sampledPoints = new Point3D[pointsToSample];
136+
137+
int idx = 0;
138+
for (int i = 0; i < numVertices && idx < MAX_POINTS_TO_RENDER; i += stride)
139+
{
140+
int base = 3 * i;
141+
if (base + 2 >= vertices.length)
142+
break;
143+
144+
sampledPoints[idx++] = new Point3D(vertices[base], vertices[base + 1], vertices[base + 2]);
145+
}
146+
147+
// Only send what we actually filled
148+
if (idx < sampledPoints.length)
149+
{
150+
Point3D[] trimmed = new Point3D[idx];
151+
System.arraycopy(sampledPoints, 0, trimmed, 0, idx);
152+
sampledPoints = trimmed;
153+
}
154+
155+
occupancyRenderer.updateMesh(sampledPoints);
156+
}
157+
99158
@Override
100159
public void dispose()
101160
{

ihmc-perception/src/main/java/us/ihmc/sensors/zed/ZEDImageSensor.java

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -510,48 +510,95 @@ public void enableSpatialMapping(boolean enable)
510510
*/
511511
private void updateMeshData()
512512
{
513-
try
513+
// Use IntPointers for output parameters to ensure we read C-side writes
514+
try (IntPointer nbVerticesPerSubmesh = new IntPointer(1000);
515+
IntPointer nbTrianglesPerSubmesh = new IntPointer(1000);
516+
IntPointer nbSubmeshes = new IntPointer(1);
517+
IntPointer updatedIndices = new IntPointer(1000);
518+
IntPointer nbVerticesTot = new IntPointer(1);
519+
IntPointer nbTrianglesTot = new IntPointer(1))
514520
{
515-
// Extract the complete spatial map
516-
sl_extract_whole_spatial_map(cameraID);
517-
518-
// Get mesh size information
519521
int maxSubmesh = 1000;
520-
int[] nbVerticesPerSubmesh = new int[maxSubmesh];
521-
int[] nbTrianglesPerSubmesh = new int[maxSubmesh];
522-
int[] nbSubmeshes = new int[1];
523-
int[] updatedIndices = new int[maxSubmesh];
524-
int[] nbVerticesTot = new int[1];
525-
int[] nbTrianglesTot = new int[1];
526522

527-
sl_update_mesh(cameraID, nbVerticesPerSubmesh, nbTrianglesPerSubmesh, nbSubmeshes, updatedIndices, nbVerticesTot, nbTrianglesTot, maxSubmesh);
523+
int mappingState = sl_get_spatial_mapping_state(cameraID);
524+
LogTools.debug("Spatial mapping state: {}", mappingState);
525+
switch (mappingState)
526+
{
527+
case SL_SPATIAL_MAPPING_STATE_INITIALIZING:
528+
LogTools.debug("Spatial mapping initializing...");
529+
break;
530+
case SL_SPATIAL_MAPPING_STATE_OK:
531+
LogTools.debug("Spatial mapping OK");
532+
break;
533+
case SL_SPATIAL_MAPPING_STATE_NOT_ENOUGH_MEMORY:
534+
LogTools.debug("Not enough memory for spatial mapping");
535+
return;
536+
case SL_SPATIAL_MAPPING_STATE_NOT_ENABLED:
537+
LogTools.debug("Spatial mapping not enabled");
538+
return;
539+
case SL_SPATIAL_MAPPING_STATE_FPS_TOO_LOW:
540+
LogTools.debug("FPS too low for spatial mapping");
541+
return;
542+
}
528543

529-
int numVertices = nbVerticesTot[0];
530-
int numTriangles = nbTrianglesTot[0];
544+
sl_request_mesh_async(cameraID);
545+
546+
// Check if mesh is ready
547+
int meshReadyStatus = sl_get_mesh_request_status_async(cameraID);
548+
if (meshReadyStatus != SL_ERROR_CODE_SUCCESS)
549+
{
550+
LogTools.debug("Mesh not ready yet: {}", getZEDErrorName(meshReadyStatus));
551+
return;
552+
}
531553

554+
// Call update_mesh with Pointers
555+
int updateResult = sl_update_mesh(cameraID,
556+
nbVerticesPerSubmesh,
557+
nbTrianglesPerSubmesh,
558+
nbSubmeshes,
559+
updatedIndices,
560+
nbVerticesTot,
561+
nbTrianglesTot,
562+
maxSubmesh);
563+
564+
// Check result code
565+
if (updateResult != SL_ERROR_CODE_SUCCESS)
566+
{
567+
LogTools.warn("sl_update_mesh failed with error: {} ({})",
568+
getZEDErrorName(updateResult), updateResult);
569+
return;
570+
}
571+
572+
// Read values from Pointers
573+
int numVertices = nbVerticesTot.get();
574+
int numTriangles = nbTrianglesTot.get();
532575
if (numVertices > 0 && numTriangles > 0)
533576
{
534577
// Allocate arrays for mesh data
535-
float[] vertices = new float[numVertices * 3]; // x, y, z for each vertex
536-
int[] triangles = new int[numTriangles * 3]; // v1, v2, v3 indices for each triangle
537-
byte[] colors = new byte[numVertices * 4]; // RGBA for each vertex
538-
float[] uvs = null; // Texture coordinates (not needed if save_texture is false)
539-
byte[] texturePtr = null; // Texture data (not needed if save_texture is false)
578+
float[] vertices = new float[numVertices * 3];
579+
int[] triangles = new int[numTriangles * 3];
580+
byte[] colors = new byte[numVertices * 4];
581+
float[] uvs = null;
582+
byte[] texturePtr = null;
540583

541-
// Retrieve mesh data
542-
sl_retrieve_mesh(cameraID, vertices, triangles, colors, uvs, texturePtr, nbSubmeshes[0]);
584+
// Retrieve using the calculated sizes
585+
int retrieveResult = sl_retrieve_mesh(cameraID, vertices, triangles, colors, uvs, texturePtr, maxSubmesh);
543586

544-
// Store mesh data in fields
545-
synchronized (this)
587+
if (retrieveResult == SL_ERROR_CODE_SUCCESS)
546588
{
547-
meshVertices = vertices;
548-
meshTriangles = triangles;
549-
meshColors = colors;
550-
meshNumVertices = numVertices;
551-
meshNumTriangles = numTriangles;
589+
synchronized (this)
590+
{
591+
meshVertices = vertices;
592+
meshTriangles = triangles;
593+
meshColors = colors;
594+
meshNumVertices = numVertices;
595+
meshNumTriangles = numTriangles;
596+
}
597+
}
598+
else
599+
{
600+
LogTools.error("Failed to retrieve mesh: " + getZEDErrorName(retrieveResult));
552601
}
553-
554-
LogTools.info("Mesh updated: {} vertices, {} triangles (from {} submeshes)", numVertices, numTriangles, nbSubmeshes[0]);
555602
}
556603
}
557604
catch (Exception e)

0 commit comments

Comments
 (0)