Skip to content

Commit 9f3ace9

Browse files
committed
add adaptive topic name based on camera name, add disparity parameters to launch file, streamline postprocess
1 parent 452ca2a commit 9f3ace9

File tree

4 files changed

+61
-37
lines changed

4 files changed

+61
-37
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ There is no need to launch the RealSense ROS wrapper separately, as they are int
5757
### Parameters
5858
There are many parameters you can tune that come with RealSense, but some of the most important ones are:
5959

60-
1. `camera_namespace` and `camera_name`: the topic name of your camera in ROS2 will be in the form of `camera_namespace/camera_name/xxx
60+
1. `camera_namespace` and `camera_name`: the topic name of your camera in ROS2 will be in the form of `camera_namespace/camera_name/xxx`
61+
a. The convention I am using is that I set `camera_name` to be the model name.
62+
**Note** that if you use D405, please put the string `D405` somewhere in the `camera_name`, as some logic later on depends on it. This is due to some quirkiness of D405 specifically.
6163

6264
2. `save_folder`: indicates where to save the `.png` of the depth and color images.
6365

realsense_capture/launch/realsense_sys_launch.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
configurable_parameters = [{'name': 'camera_namespace', 'default': 'xArm6', 'description': 'namespace for camera'},
3030
{'name': 'camera_name', 'default': 'D405', 'description': 'camera unique name'},
31-
{'name': 'save_folder', 'default': '/home/zf540/Desktop/save_folder/', 'description': 'folder to save images'},
32-
{'name': 'json_path', 'default': '/home/zf540/Desktop/save_folder/realsense_transform.json', 'description': 'path to the logging json file. This is different from RealSense JSON parameter. If empty, no logging will be done'},
31+
{'name': 'save_folder', 'default': '/home/irving/Desktop/save_folder', 'description': 'folder to save images'},
32+
{'name': 'json_path', 'default': '/home/irving/Desktop/save_folder/realsense_transform.json', 'description': 'path to the logging json file. This is different from RealSense JSON parameter. If empty, no logging will be done'},
3333
{'name': 'serial_no', 'default': "''", 'description': 'choose device by serial number'},
3434
{'name': 'usb_port_id', 'default': "''", 'description': 'choose device by usb port id'},
3535
{'name': 'device_type', 'default': "''", 'description': 'choose device by type'},
@@ -41,15 +41,15 @@
4141
{'name': 'log_level', 'default': 'info', 'description': 'debug log level [DEBUG|INFO|WARN|ERROR|FATAL]'},
4242
{'name': 'output', 'default': 'screen', 'description': 'pipe node output [screen|log]'},
4343
{'name': 'enable_color', 'default': 'true', 'description': 'enable color stream'},
44-
{'name': 'rgb_camera.color_profile', 'default': '1280x720x30', 'description': 'color stream profile'},
44+
{'name': 'rgb_camera.color_profile', 'default': '640x480x15', 'description': 'color stream profile'},
4545
{'name': 'rgb_camera.color_format', 'default': 'RGB8', 'description': 'color stream format'},
4646
{'name': 'rgb_camera.enable_auto_exposure', 'default': 'true', 'description': 'enable/disable auto exposure for color image'},
4747
{'name': 'enable_depth', 'default': 'true', 'description': 'enable depth stream'},
4848
{'name': 'enable_infra', 'default': 'false', 'description': 'enable infra0 stream'},
4949
{'name': 'enable_infra1', 'default': 'false', 'description': 'enable infra1 stream'},
5050
{'name': 'enable_infra2', 'default': 'false', 'description': 'enable infra2 stream'},
51-
{'name': 'depth_module.color_profile', 'default': '1280x720x30', 'description': 'depth stream color profile'},
52-
{'name': 'depth_module.depth_profile', 'default': '1280x720x30', 'description': 'depth stream profile'},
51+
{'name': 'depth_module.color_profile', 'default': '640x480x15', 'description': 'depth stream color profile'},
52+
{'name': 'depth_module.depth_profile', 'default': '640x480x15', 'description': 'depth stream profile'},
5353
{'name': 'depth_module.depth_format', 'default': 'Z16', 'description': 'depth stream format'},
5454
{'name': 'depth_module.infra_profile', 'default': '0,0,0', 'description': 'infra streams (0/1/2) profile'},
5555
{'name': 'depth_module.infra_format', 'default': 'RGB8', 'description': 'infra0 stream format'},
@@ -86,7 +86,8 @@
8686
{'name': 'decimation_filter.enable', 'default': 'true', 'description': 'enable_decimation_filter'},
8787
{'name': 'spatial_filter.enable', 'default': 'true', 'description': 'enable_spatial_filter'},
8888
{'name': 'temporal_filter.enable', 'default': 'true', 'description': 'enable_temporal_filter'},
89-
{'name': 'disparity_filter.enable', 'default': 'false', 'description': 'enable_disparity_filter'},
89+
{'name': 'disparity_filter.enable', 'default': 'true', 'description': 'enable_disparity_filter'},
90+
{'name': 'disparity_to_depth.enable', 'default': 'true', 'description': 'enable_disparity_filter'},
9091
{'name': 'hole_filling_filter.enable', 'default': 'false', 'description': 'enable_hole_filling_filter'},
9192
{'name': 'hdr_merge.enable', 'default': 'true', 'description': 'hdr_merge filter enablement flag'},
9293
{'name': 'wait_for_device_timeout', 'default': '-1.', 'description': 'Timeout for waiting for device to connect (Seconds)'},

realsense_capture/realsense_capture/realsense_image_client.py

+43-29
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pydoc import cli
12
from realsense_interface_msg.srv import TakeImage
23

34
from sensor_msgs.msg import Joy
@@ -120,52 +121,50 @@ def postprocess(self, img, modality):
120121

121122
encoded_img = self.cvbridge.imgmsg_to_cv2(img_msg=img,
122123
desired_encoding='passthrough')
123-
# color the log message in blue
124-
color_start = '\033[94m'
125-
color_reset = '\033[0m'
126-
127-
if self.save_folder != '':
128-
if modality == 'rgb':
129-
cv2.imwrite(os.path.join(self.save_folder, modality, f'{modality}_{self.rgb_count}.png'),
130-
cv2.cvtColor(encoded_img, cv2.COLOR_RGB2BGR))
131-
else:
132-
cv2.imwrite(os.path.join(self.save_folder, modality, f'{modality}_{self.depth_count}.png'),
133-
encoded_img)
134-
self.get_logger().info(f'{color_start}{modality} image saved{color_reset}')
135-
else:
136-
self.get_logger().info(f'{color_start}{modality} image captured, not saved{color_reset}')
137-
124+
138125
if modality == 'rgb':
126+
# save the image
127+
self._log_image(encoded_img, modality)
128+
139129
# publish the image
140130
self.rgb_publisher.publish(img)
141131

142132
'''
143133
only update json with RGB. We treat depth as an accessory
144134
'''
145-
# update the json dict
146-
if self.json_path != '':
147-
self._json_update()
148-
149-
# overwrite the JSON file if there is one. Not sure if this is the best way to do it
150-
# potentially we can just keep the json_dict in memory and dump it at the end of the program
151-
# but this is a good way to keep the json file updated in case the program cannot exit as expected
152-
with open(self.json_path, 'wt') as f:
153-
json.dump(self.json_dict, f)
154-
155-
# color the log message in green
156-
color_start = '\033[92m'
157-
color_reset = '\033[0m'
158-
self.get_logger().info(f'{color_start}JSON file updated{color_reset}')
135+
self._json_update()
159136

160137
# only increase the count with RGB so we don't double count
161138
self.rgb_count += 1
162139

163140
elif modality == 'depth':
141+
self._log_image(encoded_img, modality)
164142
self.depth_publisher.publish(img)
165143
self.depth_count += 1
166144

167145
return encoded_img
168146

147+
def _log_image(self, img, modality):
148+
'''
149+
Save the image to disk
150+
'''
151+
# color the save log message in blue
152+
save_color_start = '\033[94m'
153+
save_color_reset = '\033[0m'
154+
155+
if self.save_folder != '':
156+
if modality == 'rgb':
157+
cv2.imwrite(os.path.join(self.save_folder, modality, f'{modality}_{self.rgb_count}.png'),
158+
cv2.cvtColor(img, cv2.COLOR_RGB2BGR))
159+
np.save(os.path.join(self.save_folder, modality, f'{modality}_{self.rgb_count}.npy'), img)
160+
else:
161+
cv2.imwrite(os.path.join(self.save_folder, modality, f'{modality}_{self.depth_count}.png'),
162+
img)
163+
np.save(os.path.join(self.save_folder, modality, f'{modality}_{self.depth_count}.npy'), img)
164+
self.get_logger().info(f'{save_color_start}{modality} image saved{save_color_reset}')
165+
else:
166+
self.get_logger().info(f'{save_color_start}{modality} image captured, not saved{save_color_reset}')
167+
169168
def depth_postprocess(self, img):
170169
'''
171170
I didn't use this. Not sure if normalizing is necessary anymore after I started to use cv_bridge. But keep it just in case
@@ -221,6 +220,21 @@ def _json_setup(self, calibration_path):
221220
[0.0, 0.0, 1.0, 0.0]], dtype=np.float64).tolist()
222221

223222
def _json_update(self):
223+
224+
# color the json log message in green
225+
json_color_start = '\033[92m'
226+
json_color_reset = '\033[0m'
227+
228+
if self.json_path != '':
229+
self._json_update_helper()
230+
# overwrite the JSON file if there is one. Not sure if this is the best way to do it
231+
# potentially we can just keep the json_dict in memory and dump it at the end of the program
232+
# but this is a good way to keep the json file updated in case the program cannot exit as expected
233+
with open(self.json_path, 'wt') as f:
234+
json.dump(self.json_dict, f)
235+
self.get_logger().info(f'{json_color_start}JSON file updated{json_color_reset}')
236+
237+
def _json_update_helper(self):
224238
'''
225239
Update the json dict with the latest transform
226240
'''

realsense_capture/realsense_capture/realsense_image_server.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from calendar import c
12
import rclpy
23
from rclpy.node import Node
34
from rclpy.callback_groups import ReentrantCallbackGroup
@@ -24,10 +25,16 @@ def __init__(self):
2425
self.camera_name = self.get_parameter('camera_name').get_parameter_value().string_value
2526

2627
############################ Subscriber Setup ########################################
28+
# The topic name is different for D405 due to the fact that D405 reconstructs RGB from depth
29+
if 'D405' in self.camera_name:
30+
rgb_topic_name = 'image_rect_raw'
31+
else:
32+
rgb_topic_name = 'image_raw'
33+
2734
# Subscribe to rgb
2835
self.rgb_sub = self.create_subscription(
2936
msg_type = Image,
30-
topic = f'/{self.camere_namespace}/{self.camera_name}/color/image_rect_raw',
37+
topic = f'/{self.camere_namespace}/{self.camera_name}/color/{rgb_topic_name}',
3138
callback = functools.partial(self.sub_image_callback, 'rgb'),
3239
qos_profile = 10,
3340
callback_group = multithread_group)

0 commit comments

Comments
 (0)