Skip to content

Commit 648fa52

Browse files
authored
Switch to Compressed Depth Images (#132)
* Switch the compressedDepth * If food on fork has too few points, treat it as no FoF after acquisition
1 parent fcbbb18 commit 648fa52

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

feeding_web_app_ros2_test/feeding_web_app_ros2_test/DummyRealSense.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
# Standard imports
4+
import array
45
import threading
56

67
# Third-party imports
@@ -13,6 +14,16 @@
1314
from sensor_msgs.msg import CompressedImage, Image, CameraInfo
1415

1516

17+
# The fixed header that ROS2 Humble's compressed depth image transport plugin prepends to
18+
# the data. The exact value was empirically determined, but the below link shows the code
19+
# that prepends additional data:
20+
#
21+
# https://github.com/ros-perception/image_transport_plugins/blob/5ef79d74c4347e6a2d151df63230d5fea1357137/compressed_depth_image_transport/src/codec.cpp#L337
22+
COMPRESSED_DEPTH_16UC1_HEADER = array.array(
23+
"B", [0, 0, 0, 0, 46, 32, 133, 4, 192, 24, 60, 78]
24+
)
25+
26+
1627
class DummyRealSense(Node):
1728
"""
1829
Reads in a video file and publishes the frames as ROS2 messages.
@@ -80,7 +91,7 @@ def __init__(self):
8091
CompressedImage, "~/compressed_image", 1
8192
)
8293
self.aligned_depth_publisher = self.create_publisher(
83-
Image, "~/aligned_depth", 1
94+
CompressedImage, "~/aligned_depth", 1
8495
)
8596
self.camera_info_publisher = self.create_publisher(
8697
CameraInfo, "~/camera_info", 1
@@ -163,11 +174,24 @@ def publish_frames(self):
163174
)
164175

165176
# Configure the depth Image message
166-
depth_frame_msg = self.bridge.cv2_to_imgmsg(self.depth_frame, "passthrough")
177+
depth_frame_msg = CompressedImage()
167178
depth_frame_msg.header.frame_id = "camera_color_optical_frame"
168179
depth_frame_msg.header.stamp = (
169180
self.get_clock().now() - rclpy.duration.Duration(seconds=0.15)
170181
).to_msg()
182+
depth_frame_msg.format = "16UC1; compressedDepth"
183+
success, data = cv2.imencode(
184+
".png",
185+
self.depth_frame,
186+
# PNG compression 1 is the best speed setting, and is the setting
187+
# we use for our RealSense.
188+
[cv2.IMWRITE_PNG_COMPRESSION, 1],
189+
)
190+
if not success:
191+
raise RuntimeError("Failed to compress image")
192+
depth_frame_msg.data = (
193+
COMPRESSED_DEPTH_16UC1_HEADER.tobytes() + data.tobytes()
194+
)
171195

172196
# Configure the Camera Info
173197
self.camera_info_msg.header.stamp = depth_frame_msg.header.stamp

feeding_web_app_ros2_test/launch/feeding_web_app_dummy_nodes_launch.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<node pkg="feeding_web_app_ros2_test" exec="DummyRealSense" name="DummyRealSense">
2323
<remap from="~/image" to="/camera/color/image_raw"/>
2424
<remap from="~/compressed_image" to="/camera/color/image_raw/compressed"/>
25-
<remap from="~/aligned_depth" to="/camera/aligned_depth_to_color/image_raw"/>
25+
<remap from="~/aligned_depth" to="/camera/aligned_depth_to_color/image_raw/compressedDepth"/>
2626
<remap from="~/camera_info" to="/camera/color/camera_info"/>
2727
<remap from="~/aligned_depth/camera_info" to="/camera/aligned_depth_to_color/camera_info"/>
2828
<param name="fps" value="15"/>

feedingwebapp/src/Pages/Home/MealStates/BiteAcquisitionCheck.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,24 @@ const BiteAcquisitionCheck = () => {
137137
(message) => {
138138
console.log('Got food-on-fork detection message', message)
139139
// Only auto-continue if the previous state was Bite Acquisition
140-
if (biteAcquisitionCheckAutoContinue && prevMealState === MEAL_STATE.R_BiteAcquisition && message.status === 1) {
140+
if (biteAcquisitionCheckAutoContinue && prevMealState === MEAL_STATE.R_BiteAcquisition) {
141141
let callbackFn = null
142-
if (message.probability < biteAcquisitionCheckAutoContinueProbThreshLower) {
142+
if (message.status === -1 || (message.status === 1 && message.probability < biteAcquisitionCheckAutoContinueProbThreshLower)) {
143143
console.log('No FoF. Auto-continuing in ', remainingSeconds, ' seconds')
144144
if (timerWasForFof.current === true) {
145145
clearTimer()
146146
}
147147
timerWasForFof.current = false
148148
callbackFn = acquisitionFailure
149-
} else if (message.probability > biteAcquisitionCheckAutoContinueProbThreshUpper) {
149+
} else if (message.status === 1 && message.probability > biteAcquisitionCheckAutoContinueProbThreshUpper) {
150150
console.log('FoF. Auto-continuing in ', remainingSeconds, ' seconds')
151151
if (timerWasForFof.current === false) {
152152
clearTimer()
153153
}
154154
timerWasForFof.current = true
155155
callbackFn = acquisitionSuccess
156156
} else {
157-
console.log('Not auto-continuing due to probability between thresholds')
157+
console.log('Not auto-continuing due to probability between thresholds or errors')
158158
clearTimer()
159159
}
160160
// Don't override an existing timer

0 commit comments

Comments
 (0)