Skip to content

Commit 2581f82

Browse files
Cleaned up the DepthImageBodyCollisionFilter in java and in c++, moved it above the RapidHeightMapManager. Deleted the duplicate thread for the height map (#798)
* Split the autonomy height map thread and the continuous hiking height map thread * Close kernel before the rest of the objeccts * Change things to use the EnvironmentHandler rather then setting the HeightMapData and the TerrainMapData individually * Moved the snapping extractor out of the RapidHeightMapManager and to a higher level closer to where its used * Renaming the methods didn't catch everything * Fix snapping test * Remove duplicate variable * Uncomment bounds check * Need to increase window height to go down stairs * Cleaned up the DepthImageBodyCollisionFilter in java and in c++, moved it above the RapidHeightMapManager. Deleted the duplicate thread for the height map * Don't need to call get here
1 parent 7086a31 commit 2581f82

File tree

7 files changed

+87
-223
lines changed

7 files changed

+87
-223
lines changed

ihmc-high-level-behaviors/src/main/java/us/ihmc/perception/RapidHeightMapAutonomyUpdateThread.java

-98
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,33 @@
11
package us.ihmc.perception;
22

3-
import com.google.common.util.concurrent.ThreadFactoryBuilder;
3+
import org.bytedeco.opencv.opencv_core.GpuMat;
44
import us.ihmc.avatar.drcRobot.ROS2SyncedRobotModel;
5-
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
65
import us.ihmc.humanoidRobotics.communication.ControllerFootstepQueueMonitor;
6+
import us.ihmc.commons.thread.RepeatingTaskThread;
7+
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
78
import us.ihmc.log.LogTools;
9+
import us.ihmc.perception.camera.CameraIntrinsics;
10+
import us.ihmc.perception.filters.DepthImageBodyCollisionFilter;
811
import us.ihmc.perception.gpuHeightMap.RapidHeightMapManager;
9-
import us.ihmc.perception.heightMap.TerrainMapData;
1012
import us.ihmc.robotics.physics.RobotCollisionModel;
1113
import us.ihmc.robotics.robotSide.RobotSide;
1214
import us.ihmc.ros2.ROS2Node;
1315
import us.ihmc.sensorProcessing.heightMap.HeightMapData;
1416
import us.ihmc.sensorProcessing.heightMap.HeightMapParameters;
1517
import us.ihmc.sensors.ImageSensor;
1618

17-
import java.util.concurrent.Executors;
18-
import java.util.concurrent.ScheduledExecutorService;
19-
import java.util.concurrent.ThreadFactory;
20-
import java.util.concurrent.TimeUnit;
19+
import java.time.Instant;
2120

22-
public class RapidHeightMapThread
21+
public class RapidHeightMapThread extends RepeatingTaskThread
2322
{
23+
private final DepthImageBodyCollisionFilter bodyCollisionFilter;
2424
private final RapidHeightMapManager heightMapManager;
2525
private final Object heightMapLock = new Object();
2626

2727
private final ImageSensor imageSensor;
28-
private final ReferenceFrame sensorFrame;
28+
private final ReferenceFrame cameraFrame;
2929
private final ReferenceFrame zUpSensorFrame;
3030
private final int depthImageKey;
31-
private ScheduledExecutorService scheduler;
3231

3332
public RapidHeightMapThread(ROS2Node ros2Node,
3433
ROS2SyncedRobotModel syncedRobotModel,
@@ -38,17 +37,19 @@ public RapidHeightMapThread(ROS2Node ros2Node,
3837
ControllerFootstepQueueMonitor controllerFootstepQueueMonitor,
3938
HeightMapParameters heightMapParameters)
4039
{
40+
super(imageSensor.getSensorName() + RapidHeightMapThread.class.getSimpleName());
41+
4142
this.imageSensor = imageSensor;
4243
this.depthImageKey = depthImageKey;
4344

44-
sensorFrame = syncedRobotModel.getReferenceFrames().getSteppingCameraFrame();
45+
cameraFrame = syncedRobotModel.getReferenceFrames().getSteppingCameraFrame();
4546
zUpSensorFrame = syncedRobotModel.getReferenceFrames().getSteppingCameraZUpFrame();
4647

4748
ReferenceFrame leftFootFrame = syncedRobotModel.getReferenceFrames().getSoleFrame(RobotSide.LEFT);
4849
ReferenceFrame rightFootFrame = syncedRobotModel.getReferenceFrames().getSoleFrame(RobotSide.LEFT);
4950

51+
bodyCollisionFilter = new DepthImageBodyCollisionFilter(robotCollisionModel, syncedRobotModel.getFullRobotModel().getRootBody());
5052
heightMapManager = new RapidHeightMapManager(ros2Node,
51-
robotCollisionModel,
5253
syncedRobotModel.getFullRobotModel(),
5354
syncedRobotModel.getRobotModel().getSimpleRobotName(),
5455
leftFootFrame,
@@ -57,29 +58,35 @@ public RapidHeightMapThread(ROS2Node ros2Node,
5758
heightMapParameters);
5859
}
5960

60-
public void start()
61-
{
62-
// We create a ThreadFactory here so that when profiling the thread, there is a user-friendly name to identify it with
63-
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("RemoteHeightMapUpdateThread").build();
64-
scheduler = Executors.newScheduledThreadPool(1, threadFactory);
65-
scheduler.scheduleWithFixedDelay(this::update, 100, 10, TimeUnit.MILLISECONDS);
66-
}
67-
68-
public void update()
61+
@Override
62+
protected void runTask()
6963
{
7064
try
7165
{
7266
imageSensor.waitForGrab();
7367
RawImage depthImage = imageSensor.getImage(depthImageKey);
7468

69+
// Get everything we need from the image
70+
GpuMat latestDepthImage = depthImage.getGpuImageMat();
71+
Instant acquisitionTime = depthImage.getAcquisitionTime();
72+
CameraIntrinsics depthIntrinsicsCopy = depthImage.getIntrinsicsCopy();
73+
74+
// Process body collisions
75+
GpuMat depthImageWithoutBodyCollisions = new GpuMat(latestDepthImage.size(), latestDepthImage.type());
76+
bodyCollisionFilter.process(latestDepthImage, depthImageWithoutBodyCollisions, depthIntrinsicsCopy, cameraFrame);
77+
7578
// Update height map
7679
synchronized (heightMapLock)
7780
{
78-
heightMapManager.updateAndPublishHeightMap(depthImage, sensorFrame, zUpSensorFrame);
81+
heightMapManager.updateAndPublishHeightMap(depthImageWithoutBodyCollisions, acquisitionTime, depthIntrinsicsCopy, cameraFrame, zUpSensorFrame);
7982
}
8083

84+
depthImageWithoutBodyCollisions.close();
8185
depthImage.release();
8286
}
87+
catch (InterruptedException ignored)
88+
{
89+
}
8390
catch (Exception e)
8491
{
8592
LogTools.error(e);
@@ -94,9 +101,12 @@ public HeightMapData getLatestHeightMapData()
94101
}
95102
}
96103

97-
public void destroy()
104+
@Override
105+
public void kill()
98106
{
99-
scheduler.shutdown();
107+
super.kill();
108+
interrupt();
109+
100110
heightMapManager.destroy();
101111
}
102112
}

ihmc-high-level-behaviors/src/main/java/us/ihmc/perception/StandAloneRealsenseProcess.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public StandAloneRealsenseProcess(ROS2Node ros2Node,
8787
RealSenseImageSensor.DEPTH_IMAGE_KEY,
8888
controllerFootstepQueueMonitor,
8989
heightMapParameters);
90-
rapidHeightMapThread.start();
90+
rapidHeightMapThread.startRepeating();
9191
}
9292

9393
public HeightMapData getLatestHeightMapData()
@@ -97,7 +97,7 @@ public HeightMapData getLatestHeightMapData()
9797

9898
public void destroy()
9999
{
100-
rapidHeightMapThread.destroy();
100+
rapidHeightMapThread.blockingKill();
101101
realsenseDemandNode.destroy();
102102
realsensePublishDemandNode.destroy();
103103
d455Sensor.close();

ihmc-perception/src/main/java/us/ihmc/perception/cuda/CUDABodyCollisionFilter.java renamed to ihmc-perception/src/main/java/us/ihmc/perception/filters/DepthImageBodyCollisionFilter.java

+28-41
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package us.ihmc.perception.cuda;
1+
package us.ihmc.perception.filters;
22

33
import org.bytedeco.cuda.cudart.CUstream_st;
44
import org.bytedeco.cuda.cudart.dim3;
@@ -7,7 +7,13 @@
77
import us.ihmc.euclid.referenceFrame.FrameCapsule3D;
88
import us.ihmc.euclid.referenceFrame.FrameSphere3D;
99
import us.ihmc.euclid.referenceFrame.ReferenceFrame;
10+
import us.ihmc.mecano.multiBodySystem.interfaces.RigidBodyBasics;
1011
import us.ihmc.perception.camera.CameraIntrinsics;
12+
import us.ihmc.perception.cuda.CUDAKernel;
13+
import us.ihmc.perception.cuda.CUDAProgram;
14+
import us.ihmc.perception.cuda.CUDAStreamManager;
15+
import us.ihmc.perception.cuda.CUDATools;
16+
import us.ihmc.robotics.physics.RobotCollisionModel;
1117
import us.ihmc.scs2.simulation.collision.Collidable;
1218

1319
import java.net.URL;
@@ -16,8 +22,15 @@
1622
import static org.bytedeco.cuda.global.cudart.cudaFree;
1723
import static org.bytedeco.cuda.global.cudart.cudaStreamSynchronize;
1824

19-
public class CUDABodyCollisionFilter
25+
/**
26+
* This class removes the points of a depth image that are on parts of the body.
27+
* This class expects a {@link RobotCollisionModel} and a root body in the form of a {@link RigidBodyBasics}.
28+
* This class runs a CUDA GPU kernel that checks if a point lies inside any collisions on the {@link RobotCollisionModel}.
29+
* The returned value represents a depth image that has zeroed out points for anything that was a collision.
30+
*/
31+
public class DepthImageBodyCollisionFilter
2032
{
33+
private static final boolean PRINT_DEBUG_TIMINGS = false;
2134
private static final int BLOCK_SIZE_XY = 32;
2235
private final int NUMBER_OF_ATTRIBUTES = 7;
2336

@@ -31,33 +44,30 @@ public class CUDABodyCollisionFilter
3144
private final FloatPointer deviceCollidableGeometryPointer;
3245
private final FloatPointer collidableGeometryPointer;
3346

34-
public CUDABodyCollisionFilter(List<Collidable> robotCollidables)
47+
public DepthImageBodyCollisionFilter(RobotCollisionModel robotCollisionModel, RigidBodyBasics rootBody)
3548
{
36-
this.robotCollidables = robotCollidables;
37-
URL bodyCollisionCheckURL = getClass().getResource("BodyCollisionCheck.cu");
38-
URL utilsURL = getClass().getResource("Utils.cu");
39-
URL perceptionUtilsURL = getClass().getResource("PerceptionUtils.cu");
40-
URL mathUtilsURL = getClass().getResource("MathUtils.cuh");
49+
robotCollidables = robotCollisionModel.getRobotCollidables(rootBody);
50+
51+
URL bodyCollisionCheckURL = getClass().getResource("DepthImageBodyCollisionFilter.cu");
52+
URL perceptionUtilsURL = getClass().getClassLoader().getResource("us/ihmc/perception/cuda/PerceptionUtils.cu");
53+
URL mathUtilsURL = getClass().getClassLoader().getResource("us/ihmc/perception/cuda/MathUtils.cuh");
4154

4255
try
4356
{
44-
program = new CUDAProgram(bodyCollisionCheckURL, utilsURL, perceptionUtilsURL, mathUtilsURL);
57+
program = new CUDAProgram(bodyCollisionCheckURL, perceptionUtilsURL, mathUtilsURL);
4558
kernel = program.loadKernel("checkBodyCollision");
59+
kernel.enableKernelTimings(PRINT_DEBUG_TIMINGS);
4660
}
4761
catch (Exception e)
4862
{
4963
throw new RuntimeException(e);
5064
}
5165

5266
stream = CUDAStreamManager.getStream();
53-
if (stream == null)
54-
{
55-
throw new RuntimeException("CUDA stream could not be initialized!");
56-
}
5767

5868
// Note: We get the expected number of collidables and allocate that memory amount on the GPU
5969
// By allocating once we don't have to free the memory in each call, just at the end
60-
numberOfCollidables = countSupportedCollidables(robotCollidables);
70+
numberOfCollidables = robotCollidables.size();
6171
dataSize = numberOfCollidables * NUMBER_OF_ATTRIBUTES;
6272
deviceCollidableGeometryPointer = new FloatPointer();
6373
CUDATools.mallocAsync(deviceCollidableGeometryPointer, dataSize, stream);
@@ -107,31 +117,15 @@ public void process(GpuMat deviceInputDepthImage, GpuMat deviceOutputImageToPack
107117
gridSize.close();
108118
}
109119

110-
private int countSupportedCollidables(List<Collidable> robotCollidables)
111-
{
112-
if (robotCollidables == null)
113-
return 0;
114-
115-
int count = 0;
116-
for (Collidable collidable : robotCollidables)
117-
{
118-
if (isCollidableShapeSupported(collidable))
119-
{
120-
count++;
121-
}
122-
}
123-
return count;
124-
}
125-
126-
public void getCollidablesPointer(List<Collidable> robotCollidables, ReferenceFrame cameraFrame)
120+
/**
121+
* The supported collidables are a {@link FrameSphere3D} and a {@link FrameCapsule3D}
122+
*/
123+
private void getCollidablesPointer(List<Collidable> robotCollidables, ReferenceFrame cameraFrame)
127124
{
128125
int index = 0;
129126

130127
for (Collidable collidable : robotCollidables)
131128
{
132-
if (!isCollidableShapeSupported(collidable))
133-
continue;
134-
135129
if (collidable.getShape() instanceof FrameSphere3D sphere)
136130
{
137131
FrameSphere3D bodypart = new FrameSphere3D(sphere);
@@ -159,13 +153,6 @@ else if (collidable.getShape() instanceof FrameCapsule3D capsule)
159153
}
160154
}
161155

162-
private boolean isCollidableShapeSupported(Collidable collidable)
163-
{
164-
return (collidable.getShape() instanceof FrameCapsule3D || collidable.getShape() instanceof FrameSphere3D) && !collidable.getRigidBody()
165-
.getName()
166-
.matches("TORSO_LINK|PELVIS_LINK");
167-
}
168-
169156
public void close()
170157
{
171158
// Need to free this memory on the GPU to shut down correctly

ihmc-perception/src/main/java/us/ihmc/perception/gpuHeightMap/RapidHeightMapExtractorCUDA.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ public void destroy()
391391
planOffsetKernel.close();
392392

393393
emptyGlobalHeightMapImage.close();
394-
planOffsetKernelGridDim.close();
394+
if (planOffsetKernelGridDim != null)
395+
planOffsetKernelGridDim.close();
395396

396397
// Clean up each resource
397398
deallocateFloatPointer(groundToSensorTransformHostPointer, groundToSensorTransformDevicePointer);

0 commit comments

Comments
 (0)