Add ob_benchmark_node tool and benchmark examples

This commit is contained in:
jj
2025-02-10 15:57:15 +08:00
parent ff40e1d2c5
commit e0f308da12
8 changed files with 1160 additions and 0 deletions
+13
View File
@@ -218,6 +218,7 @@ add_orbbec_executable(topic_statistics_node tools/topic_statistics.cpp)
add_orbbec_executable(multi_save_rgbir_node tools/multi_save_rgbir_node.cpp)
add_orbbec_executable(metadata_save_files_node tools/metadata_save_files.cpp)
add_orbbec_executable(metadata_export_files_node tools/metadata_export_files.cpp)
add_orbbec_executable(ob_benchmark_node tools/ob_benchmark.cpp)
add_library(frame_latency SHARED tools/frame_latency.cpp)
target_include_directories(frame_latency PUBLIC ${COMMON_INCLUDE_DIRS})
@@ -229,8 +230,19 @@ rclcpp_components_register_node(frame_latency
EXECUTABLE frame_latency_node
)
add_library(start_benchmark SHARED tools/start_benchmark.cpp)
target_include_directories(start_benchmark PUBLIC ${COMMON_INCLUDE_DIRS})
target_link_libraries(start_benchmark ${COMMON_LIBRARIES})
ament_target_dependencies(start_benchmark ${dependencies})
rclcpp_components_register_node(start_benchmark
PLUGIN "orbbec_camera::tools::StartBenchmark"
EXECUTABLE start_benchmark_node
)
# Install rules
install(TARGETS ${PROJECT_NAME} frame_latency
start_benchmark
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
@@ -256,6 +268,7 @@ install(TARGETS list_devices_node
multi_save_rgbir_node
metadata_save_files_node
metadata_export_files_node
ob_benchmark_node
DESTINATION lib/${PROJECT_NAME}/)
if (BUILD_TESTING)
@@ -0,0 +1,14 @@
{
"start_benchmark_params": {
"camera_name": [
"camera_01",
"camera_02",
"camera_03",
"camera_04"
],
"process_name": "component_conta",
"switch_cycle": 60,
"test_cycle": 1,
"skip_number": 30
}
}
@@ -0,0 +1 @@
@@ -0,0 +1,265 @@
import os
import yaml
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, OpaqueFunction, GroupAction
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import PushRosNamespace, ComposableNodeContainer, Node
from launch_ros.descriptions import ComposableNode
from launch.conditions import UnlessCondition
from launch_ros.actions import LoadComposableNodes
def load_yaml(file_path):
with open(file_path, 'r') as f:
return yaml.safe_load(f)
def merge_params(default_params, yaml_params):
for key, value in yaml_params.items():
if key in default_params:
default_params[key] = value
return default_params
def convert_value(value):
if isinstance(value, str):
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
if value.lower() == 'true':
return True
elif value.lower() == 'false':
return False
return value
def load_parameters(context, args):
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
config_file_path = LaunchConfiguration('config_file_path').perform(context)
if config_file_path:
yaml_params = load_yaml(config_file_path)
default_params = merge_params(default_params, yaml_params)
skip_convert = {'config_file_path', 'usb_port', 'serial_number'}
return {
key: (value if key in skip_convert else convert_value(value))
for key, value in default_params.items()
}
def generate_launch_description():
args = [
DeclareLaunchArgument('camera_name', default_value='camera'),
DeclareLaunchArgument('depth_registration', default_value='true'),
DeclareLaunchArgument('serial_number', default_value=''),
DeclareLaunchArgument('usb_port', default_value=''),
DeclareLaunchArgument('device_num', default_value='1'),
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),#libuvc or v4l2
DeclareLaunchArgument('point_cloud_qos', default_value='default'),
DeclareLaunchArgument('enable_point_cloud', default_value='true'),
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
DeclareLaunchArgument('cloud_frame_id', default_value=''),
DeclareLaunchArgument('connection_delay', default_value='10'),
DeclareLaunchArgument('color_width', default_value='0'),
DeclareLaunchArgument('color_height', default_value='0'),
DeclareLaunchArgument('color_fps', default_value='0'),
DeclareLaunchArgument('color_format', default_value='ANY'),
DeclareLaunchArgument('enable_color', default_value='true'),
DeclareLaunchArgument('color_qos', default_value='default'),
DeclareLaunchArgument('color_camera_info_qos', default_value='default'),
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
DeclareLaunchArgument('color_exposure', default_value='-1'),
DeclareLaunchArgument('color_gain', default_value='-1'),
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
DeclareLaunchArgument('color_white_balance', default_value='-1'),
DeclareLaunchArgument('color_ae_max_exposure', default_value='-1'),
DeclareLaunchArgument('color_brightness', default_value='-1'),
DeclareLaunchArgument('depth_width', default_value='0'),
DeclareLaunchArgument('depth_height', default_value='0'),
DeclareLaunchArgument('depth_fps', default_value='0'),
DeclareLaunchArgument('depth_format', default_value='ANY'),
DeclareLaunchArgument('enable_depth', default_value='true'),
DeclareLaunchArgument('depth_qos', default_value='default'),
DeclareLaunchArgument('depth_camera_info_qos', default_value='default'),
DeclareLaunchArgument('left_ir_width', default_value='0'),
DeclareLaunchArgument('left_ir_height', default_value='0'),
DeclareLaunchArgument('left_ir_fps', default_value='0'),
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_left_ir', default_value='false'),
DeclareLaunchArgument('left_ir_qos', default_value='default'),
DeclareLaunchArgument('left_ir_camera_info_qos', default_value='default'),
DeclareLaunchArgument('right_ir_width', default_value='0'),
DeclareLaunchArgument('right_ir_height', default_value='0'),
DeclareLaunchArgument('right_ir_fps', default_value='0'),
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_right_ir', default_value='false'),
DeclareLaunchArgument('right_ir_qos', default_value='default'),
DeclareLaunchArgument('right_ir_camera_info_qos', default_value='default'),
DeclareLaunchArgument('enable_ir_auto_exposure', default_value='true'),
DeclareLaunchArgument('ir_exposure', default_value='-1'),
DeclareLaunchArgument('ir_gain', default_value='-1'),
DeclareLaunchArgument('ir_ae_max_exposure', default_value='-1'),
DeclareLaunchArgument('ir_brightness', default_value='-1'),
DeclareLaunchArgument('enable_sync_output_accel_gyro', default_value='false'),
DeclareLaunchArgument('enable_accel', default_value='false'),
DeclareLaunchArgument('accel_rate', default_value='200hz'),
DeclareLaunchArgument('accel_range', default_value='4g'),
DeclareLaunchArgument('enable_gyro', default_value='false'),
DeclareLaunchArgument('gyro_rate', default_value='200hz'),
DeclareLaunchArgument('gyro_range', default_value='1000dps'),
DeclareLaunchArgument('liner_accel_cov', default_value='0.01'),
DeclareLaunchArgument('angular_vel_cov', default_value='0.01'),
DeclareLaunchArgument('publish_tf', default_value='true'),
DeclareLaunchArgument('tf_publish_rate', default_value='0.0'),
DeclareLaunchArgument('ir_info_url', default_value=''),
DeclareLaunchArgument('color_info_url', default_value=''),
DeclareLaunchArgument('log_level', default_value='none'),
DeclareLaunchArgument('enable_publish_extrinsic', default_value='false'),
DeclareLaunchArgument('enable_d2c_viewer', default_value='false'),
DeclareLaunchArgument('enable_hardware_d2d', default_value='true'),
DeclareLaunchArgument('enable_ldp', default_value='true'),
DeclareLaunchArgument('enable_soft_filter', default_value='true'),
DeclareLaunchArgument('soft_filter_max_diff', default_value='-1'),
DeclareLaunchArgument('soft_filter_speckle_size', default_value='-1'),
DeclareLaunchArgument('sync_mode', default_value='standalone'),
DeclareLaunchArgument('depth_delay_us', default_value='0'),
DeclareLaunchArgument('color_delay_us', default_value='0'),
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
DeclareLaunchArgument('ordered_pc', default_value='false'),
DeclareLaunchArgument('enable_depth_scale', default_value='true'),
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
DeclareLaunchArgument('enable_hdr_merge', default_value='false'),
DeclareLaunchArgument('enable_sequence_id_filter', default_value='false'),
DeclareLaunchArgument('enable_threshold_filter', default_value='false'),
DeclareLaunchArgument('enable_hardware_noise_removal_filter', default_value='true'),
DeclareLaunchArgument('enable_noise_removal_filter', default_value='true'),
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
DeclareLaunchArgument('threshold_filter_min', default_value='-1'),
DeclareLaunchArgument('noise_removal_filter_min_diff', default_value='256'),
DeclareLaunchArgument('noise_removal_filter_max_size', default_value='80'),
DeclareLaunchArgument('spatial_filter_alpha', default_value='-1.0'),
DeclareLaunchArgument('spatial_filter_diff_threshold', default_value='-1'),
DeclareLaunchArgument('spatial_filter_magnitude', default_value='-1'),
DeclareLaunchArgument('spatial_filter_radius', default_value='-1'),
DeclareLaunchArgument('temporal_filter_diff_threshold', default_value='-1.0'),
DeclareLaunchArgument('temporal_filter_weight', default_value='-1.0'),
DeclareLaunchArgument('hole_filling_filter_mode', default_value=''),
DeclareLaunchArgument('hdr_merge_exposure_1', default_value='-1'),
DeclareLaunchArgument('hdr_merge_gain_1', default_value='-1'),
DeclareLaunchArgument('hdr_merge_exposure_2', default_value='-1'),
DeclareLaunchArgument('hdr_merge_gain_2', default_value='-1'),
DeclareLaunchArgument('align_mode', default_value='SW'),
DeclareLaunchArgument('diagnostic_period', default_value='1.0'),
DeclareLaunchArgument('enable_laser', default_value='true'),
DeclareLaunchArgument('depth_precision', default_value=''),
DeclareLaunchArgument('device_preset', default_value='Default'),
DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'),
DeclareLaunchArgument('laser_energy_level', default_value='-1'),
DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system
DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
DeclareLaunchArgument('config_file_path', default_value=''),
DeclareLaunchArgument('enable_heartbeat', default_value='false'),
DeclareLaunchArgument('gmsl_trigger_fps', default_value='3000'),
DeclareLaunchArgument('enable_gmsl_trigger', default_value='false'),
DeclareLaunchArgument('disparity_range_mode', default_value='-1'),
DeclareLaunchArgument('disparity_search_offset', default_value='-1'),
DeclareLaunchArgument('disparity_offset_config', default_value='false'),
DeclareLaunchArgument('offset_index0', default_value='-1'),
DeclareLaunchArgument('offset_index1', default_value='-1'),
DeclareLaunchArgument('frame_aggregate_mode', default_value='ANY'), # full_frame、color_frame、ANY or disable
DeclareLaunchArgument('interleave_ae_mode', default_value='laser'), # 'hdr' or 'laser'
DeclareLaunchArgument('interleave_frame_enable', default_value='false'),
DeclareLaunchArgument('interleave_skip_enable', default_value='false'),
DeclareLaunchArgument('interleave_skip_index', default_value='1'), # 0:skip pattern ir 1: skip flood ir
DeclareLaunchArgument('hdr_index1_laser_control', default_value='1'),#interleave_hdr_param
DeclareLaunchArgument('hdr_index1_depth_exposure', default_value='1'),
DeclareLaunchArgument('hdr_index1_depth_gain', default_value='16'),
DeclareLaunchArgument('hdr_index1_ir_brightness', default_value='20'),
DeclareLaunchArgument('hdr_index1_ir_ae_max_exposure', default_value='2000'),
DeclareLaunchArgument('hdr_index0_laser_control', default_value='1'),
DeclareLaunchArgument('hdr_index0_depth_exposure', default_value='7500'),
DeclareLaunchArgument('hdr_index0_depth_gain', default_value='16'),
DeclareLaunchArgument('hdr_index0_ir_brightness', default_value='60'),
DeclareLaunchArgument('hdr_index0_ir_ae_max_exposure', default_value='10000'),
DeclareLaunchArgument('laser_index1_laser_control', default_value='0'),#interleave_laser_param
DeclareLaunchArgument('laser_index1_depth_exposure', default_value='3000'),
DeclareLaunchArgument('laser_index1_depth_gain', default_value='16'),
DeclareLaunchArgument('laser_index1_ir_brightness', default_value='60'),
DeclareLaunchArgument('laser_index1_ir_ae_max_exposure', default_value='17000'),
DeclareLaunchArgument('laser_index0_laser_control', default_value='1'),
DeclareLaunchArgument('laser_index0_depth_exposure', default_value='3000'),
DeclareLaunchArgument('laser_index0_depth_gain', default_value='16'),
DeclareLaunchArgument('laser_index0_ir_brightness', default_value='60'),
DeclareLaunchArgument('laser_index0_ir_ae_max_exposure', default_value='30000'),
DeclareLaunchArgument('use_intra_process_comms', default_value='false'),
DeclareLaunchArgument('attach_component_container_enable', default_value='false'),
DeclareLaunchArgument('attach_component_container_name', default_value='orbbec_container'),
]
def get_params(context, args):
return [load_parameters(context, args)]
def create_node_action(context, args):
params = get_params(context, args)
ros_distro = os.environ.get("ROS_DISTRO", "humble")
if ros_distro == "foxy":
return [
Node(
package="orbbec_camera",
executable="orbbec_camera_node",
name="ob_camera_node",
namespace=LaunchConfiguration("camera_name"),
parameters=params,
output="screen",
)
]
else:
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
component_container_name_arg = LaunchConfiguration('component_container_name', default='orbbec_container')
orbbec_container = Node(
name=component_container_name_arg,
package='rclcpp_components',
executable='component_container_mt',
output='screen',
condition=UnlessCondition(attach_to_shared_component_container_arg)
)
return [
# orbbec_container,
LoadComposableNodes(
target_container=component_container_name_arg,
composable_node_descriptions=[
ComposableNode(
namespace=LaunchConfiguration("camera_name"),
name=LaunchConfiguration("camera_name"),
package='orbbec_camera',
plugin='orbbec_camera::OBCameraNodeDriver',
parameters=params,
extra_arguments=[{'use_intra_process_comms': LaunchConfiguration("use_intra_process_comms")}],
)
]
)
]
return LaunchDescription(
args + [
OpaqueFunction(function=lambda context: create_node_action(context, args))
]
)
@@ -0,0 +1,197 @@
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node,LoadComposableNodes
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import DeclareLaunchArgument
from launch.conditions import UnlessCondition, IfCondition
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.descriptions import ComposableNode
def load_yaml(file_path):
with open(file_path, 'r') as f:
return yaml.safe_load(f)
def merge_params(default_params, yaml_params):
for key, value in yaml_params.items():
if key in default_params:
default_params[key] = value
return default_params
def convert_value(value):
if isinstance(value, str):
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
if value.lower() == 'true':
return True
elif value.lower() == 'false':
return False
return value
def load_parameters(context, args):
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
config_file_path = LaunchConfiguration('config_file_path').perform(context)
if config_file_path:
yaml_params = load_yaml(config_file_path)
default_params = merge_params(default_params, yaml_params)
skip_convert = {'config_file_path', 'usb_port', 'serial_number'}
return {
key: (value if key in skip_convert else convert_value(value))
for key, value in default_params.items()
}
def generate_launch_description():
# Include launch files
package_dir = get_package_share_directory("orbbec_camera")
launch_file_dir = os.path.join(package_dir, "launch")
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
component_container_name_arg = LaunchConfiguration('component_container_name', default='shared_orbbec_container')
shared_orbbec_container = Node(
name=component_container_name_arg,
package="rclcpp_components",
executable="component_container_mt",
output="screen",
condition=UnlessCondition(attach_to_shared_component_container_arg),
)
start_benchmark = LoadComposableNodes(
target_container=component_container_name_arg,
composable_node_descriptions=[
ComposableNode(
namespace="start_benchmark",
name="start_benchmark",
package='orbbec_camera',
plugin='orbbec_camera::tools::StartBenchmark',
)
]
)
attach_to_shared_component_container_arg = TextSubstitution(text="true")
args = [
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),
DeclareLaunchArgument('depth_registration', default_value='false'),
DeclareLaunchArgument('color_width', default_value='848'),
DeclareLaunchArgument('color_height', default_value='480'),
DeclareLaunchArgument('color_fps', default_value='30'),
DeclareLaunchArgument('color_format', default_value='MJPG'),
DeclareLaunchArgument('enable_color', default_value='true'),
DeclareLaunchArgument('depth_width', default_value='848'),
DeclareLaunchArgument('depth_height', default_value='480'),
DeclareLaunchArgument('depth_fps', default_value='30'),
DeclareLaunchArgument('depth_format', default_value='ANY'),
DeclareLaunchArgument('enable_depth', default_value='true'),
DeclareLaunchArgument('left_ir_width', default_value='848'),
DeclareLaunchArgument('left_ir_height', default_value='480'),
DeclareLaunchArgument('left_ir_fps', default_value='30'),
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_left_ir', default_value='true'),
DeclareLaunchArgument('right_ir_width', default_value='848'),
DeclareLaunchArgument('right_ir_height', default_value='480'),
DeclareLaunchArgument('right_ir_fps', default_value='30'),
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_right_ir', default_value='true'),
DeclareLaunchArgument('enable_point_cloud', default_value='false'),
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
DeclareLaunchArgument('enable_hdr_merge', default_value='false'),
DeclareLaunchArgument('enable_sequence_id_filter', default_value='false'),
DeclareLaunchArgument('enable_threshold_filter', default_value='false'),
DeclareLaunchArgument('enable_hardware_noise_removal_filter', default_value='false'),
DeclareLaunchArgument('enable_noise_removal_filter', default_value='false'),
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
]
launch1_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_01",
"usb_port": "2-7",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch2_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_02",
"usb_port": "2-2",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch3_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_03",
"usb_port": "2-1",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch4_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_04",
"usb_port": "2-3",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
delayed_left_camera = TimerAction(
period=2.0,
actions=args+[launch1_include],
)
delayed_right_camera = TimerAction(
period=4.0,
actions=args+[launch2_include],
)
delayed_rear_camera = TimerAction(
period=6.0,
actions=args+[launch3_include],
)
delayed_front_camera = TimerAction(
period=8.0,
actions=args+[launch4_include],
)
ld = LaunchDescription(
[
shared_orbbec_container,
start_benchmark,
delayed_left_camera,
delayed_right_camera,
delayed_rear_camera,
delayed_front_camera,
]
)
return ld
@@ -0,0 +1,197 @@
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node,LoadComposableNodes
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import DeclareLaunchArgument
from launch.conditions import UnlessCondition, IfCondition
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.descriptions import ComposableNode
def load_yaml(file_path):
with open(file_path, 'r') as f:
return yaml.safe_load(f)
def merge_params(default_params, yaml_params):
for key, value in yaml_params.items():
if key in default_params:
default_params[key] = value
return default_params
def convert_value(value):
if isinstance(value, str):
try:
return int(value)
except ValueError:
pass
try:
return float(value)
except ValueError:
pass
if value.lower() == 'true':
return True
elif value.lower() == 'false':
return False
return value
def load_parameters(context, args):
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
config_file_path = LaunchConfiguration('config_file_path').perform(context)
if config_file_path:
yaml_params = load_yaml(config_file_path)
default_params = merge_params(default_params, yaml_params)
skip_convert = {'config_file_path', 'usb_port', 'serial_number'}
return {
key: (value if key in skip_convert else convert_value(value))
for key, value in default_params.items()
}
def generate_launch_description():
# Include launch files
package_dir = get_package_share_directory("orbbec_camera")
launch_file_dir = os.path.join(package_dir, "launch")
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
component_container_name_arg = LaunchConfiguration('component_container_name', default='shared_orbbec_container')
shared_orbbec_container = Node(
name=component_container_name_arg,
package="rclcpp_components",
executable="component_container_mt",
output="screen",
condition=UnlessCondition(attach_to_shared_component_container_arg),
)
start_benchmark = LoadComposableNodes(
target_container=component_container_name_arg,
composable_node_descriptions=[
ComposableNode(
namespace="start_benchmark",
name="start_benchmark",
package='orbbec_camera',
plugin='orbbec_camera::tools::StartBenchmark',
)
]
)
attach_to_shared_component_container_arg = TextSubstitution(text="true")
args = [
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),
DeclareLaunchArgument('depth_registration', default_value='false'),
DeclareLaunchArgument('color_width', default_value='848'),
DeclareLaunchArgument('color_height', default_value='480'),
DeclareLaunchArgument('color_fps', default_value='30'),
DeclareLaunchArgument('color_format', default_value='MJPG'),
DeclareLaunchArgument('enable_color', default_value='true'),
DeclareLaunchArgument('depth_width', default_value='848'),
DeclareLaunchArgument('depth_height', default_value='480'),
DeclareLaunchArgument('depth_fps', default_value='30'),
DeclareLaunchArgument('depth_format', default_value='ANY'),
DeclareLaunchArgument('enable_depth', default_value='true'),
DeclareLaunchArgument('left_ir_width', default_value='848'),
DeclareLaunchArgument('left_ir_height', default_value='480'),
DeclareLaunchArgument('left_ir_fps', default_value='30'),
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_left_ir', default_value='true'),
DeclareLaunchArgument('right_ir_width', default_value='848'),
DeclareLaunchArgument('right_ir_height', default_value='480'),
DeclareLaunchArgument('right_ir_fps', default_value='30'),
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
DeclareLaunchArgument('enable_right_ir', default_value='true'),
DeclareLaunchArgument('enable_point_cloud', default_value='false'),
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
DeclareLaunchArgument('enable_hdr_merge', default_value='false'),
DeclareLaunchArgument('enable_sequence_id_filter', default_value='false'),
DeclareLaunchArgument('enable_threshold_filter', default_value='false'),
DeclareLaunchArgument('enable_hardware_noise_removal_filter', default_value='true'),
DeclareLaunchArgument('enable_noise_removal_filter', default_value='false'),
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
]
launch1_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_01",
"usb_port": "2-7",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch2_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_02",
"usb_port": "2-2",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch3_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_03",
"usb_port": "2-1",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
launch4_include = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, "gemini_330_series_component.launch.py")
),
launch_arguments={
"camera_name": "camera_04",
"usb_port": "2-3",
"device_num": "4",
"sync_mode": "standalone",
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
"component_container_name": component_container_name_arg,
}.items(),
)
delayed_left_camera = TimerAction(
period=2.0,
actions=args+[launch1_include],
)
delayed_right_camera = TimerAction(
period=4.0,
actions=args+[launch2_include],
)
delayed_rear_camera = TimerAction(
period=6.0,
actions=args+[launch3_include],
)
delayed_front_camera = TimerAction(
period=8.0,
actions=args+[launch4_include],
)
ld = LaunchDescription(
[
shared_orbbec_container,
start_benchmark,
delayed_left_camera,
delayed_right_camera,
delayed_rear_camera,
delayed_front_camera,
]
)
return ld
+324
View File
@@ -0,0 +1,324 @@
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_components/register_node_macro.hpp>
#include <orbbec_camera/ob_camera_node_driver.h>
#include <orbbec_camera/utils.h>
#include "orbbec_camera_msgs/msg/metadata.hpp"
#include <message_filters/subscriber.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/synchronizer.h>
#include <filesystem>
#include <cpuid.h>
namespace orbbec_camera {
namespace tools {
class ObBenchmark : public rclcpp::Node {
public:
ObBenchmark() : Node("ObBenchmark") {
params_init();
stat_process();
function_ = this->create_wall_timer(std::chrono::seconds(test_cycle_),
std::bind(&ObBenchmark::functionCallback, this));
config_ = this->create_wall_timer(std::chrono::seconds(switch_cycle_),
std::bind(&ObBenchmark::configCallback, this));
}
~ObBenchmark() { kill_process(process_name_); }
private:
rclcpp::TimerBase::SharedPtr function_;
rclcpp::TimerBase::SharedPtr config_;
std::vector<float> cpu_usage_;
std::vector<float> memory_usage_;
std::vector<std::string> current_time_;
int usage_count_ = 0;
int launch_count_ = 0;
long prevIdle = 0;
long prevTotal = 0;
std::string process_pid_;
std::string process_name_;
int switch_cycle_;
int test_cycle_;
int skip_number_;
std::mutex image_mutex_;
void params_init() {
std::ifstream file(
"install/orbbec_camera/share/orbbec_camera/config/tools/startbenchmark/"
"start_benchmark_params.json");
if (!file.is_open()) {
RCLCPP_ERROR_STREAM(this->get_logger(), "Failed to open JSON file.");
return;
}
nlohmann::json json_data;
file >> json_data;
process_name_ = json_data["start_benchmark_params"]["process_name"].get<std::string>();
switch_cycle_ = json_data["start_benchmark_params"]["switch_cycle"].get<int>();
test_cycle_ = json_data["start_benchmark_params"]["test_cycle"].get<int>();
skip_number_ = json_data["start_benchmark_params"]["skip_number"].get<int>();
}
std::string exec_command(const std::string& command) {
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
if (!pipe) {
std::cerr << "Failed to run command" << std::endl;
return "";
}
char buffer[128];
std::string result = "";
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
result += buffer;
}
return result;
}
float get_ps_cpu_usage_by_process(const std::string& process_name) {
std::string command = "ps aux | grep '" + process_name + "' | grep -v grep";
std::string result = exec_command(command);
std::istringstream stream(result);
std::string line;
float total_cpu_usage = 0.0;
while (std::getline(stream, line)) {
std::istringstream line_stream(line);
std::string user, pid, cpu, mem, command;
line_stream >> user >> pid >> cpu >> mem;
if (cpu.empty() || line.find("grep") != std::string::npos) {
continue;
}
try {
process_pid_ = pid;
float cpu_usage = std::stof(cpu);
total_cpu_usage += cpu_usage;
} catch (const std::invalid_argument& e) {
continue;
}
}
return total_cpu_usage;
}
float get_top_cpu_usage_by_process() {
std::string command =
"top -bn1 -p " + process_pid_ + " | grep '" + process_pid_ + "' | awk '{print $9}'";
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
if (!pipe) {
std::cerr << "Failed to run command" << std::endl;
return -1.0f;
}
char buffer[128];
float total_cpu_usage = 0.0f;
bool found_process = false;
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
std::stringstream ss(buffer);
float cpu_usage = 0.0f;
ss >> cpu_usage;
if (ss) {
total_cpu_usage += cpu_usage;
found_process = true;
}
}
if (!found_process) {
std::cerr << "No matching processes found for PID: " << process_pid_ << std::endl;
return -1.0f;
}
return total_cpu_usage;
}
float get_memory_usage_by_process() {
std::string command =
"top -b -n 1 -p " + process_pid_ + " | grep '" + process_pid_ + "' | awk '{print $6}'";
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
if (!pipe) {
std::cerr << "Failed to run command" << std::endl;
return -1.0f;
}
char buffer[128];
std::string result = "";
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) {
result += buffer;
}
std::stringstream ss(result);
long memory_usage_kb;
ss >> memory_usage_kb;
float memory_usage_mb = static_cast<float>(memory_usage_kb) / 1024.0f;
std::stringstream formatted_result;
formatted_result << std::fixed << std::setprecision(1) << memory_usage_mb;
return std::stof(formatted_result.str());
}
std::string get_cpu() {
unsigned int CPUInfo[4] = {0, 0, 0, 0};
char CPUBrandString[0x40] = {0};
__cpuid(0x80000000, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
for (unsigned int i = 0x80000002; i <= 0x80000004; ++i) {
__cpuid(i, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
if (i == 0x80000002) {
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
} else if (i == 0x80000003) {
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
} else if (i == 0x80000004) {
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
}
}
char* ptr = CPUBrandString;
while (*ptr == ' ') ptr++;
return std::string(ptr);
}
std::string getCurrentTimes() {
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t(now);
std::tm tm = *std::localtime(&now_time_t);
std::ostringstream date_stream;
date_stream << std::put_time(&tm, "%H:%M:%S");
std::string date_str = date_stream.str();
return date_str;
}
void ensure_directory_exists(const std::string& path) {
size_t found = path.find_last_of("/\\");
std::string dir_path = path.substr(0, found);
struct stat info;
if (stat(dir_path.c_str(), &info) != 0) {
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"Directory does not exist, creating it: " << dir_path);
if (mkdir(dir_path.c_str(), 0777) != 0) {
RCLCPP_ERROR_STREAM(this->get_logger(), "Failed to create directory: " << dir_path.c_str());
}
}
}
void save_to_csv(const std::string& filename) {
ensure_directory_exists(filename);
std::ofstream file;
file.open(filename, std::ios_base::app);
if (file.is_open()) {
file << "Time,CPU,Memory(MB)" << "\n";
for (int i = skip_number_; i < usage_count_ - 1; i++) {
file << current_time_[i] << "," << cpu_usage_[i] << "%" << "," << memory_usage_[i] << "\n";
}
float cpu_average =
std::accumulate(cpu_usage_.begin() + skip_number_, cpu_usage_.begin() + usage_count_ - 1, 0.0f) /
(usage_count_ - (skip_number_+1));
float memory_average = std::accumulate(memory_usage_.begin() + skip_number_,
memory_usage_.begin() + usage_count_ - 1, 0.0f) /
(usage_count_ - (skip_number_+1));
file << "Average: ," << cpu_average << "%, " << memory_average << "\n";
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"Average: " << cpu_average << "%" << memory_average << "MB");
file.close();
} else {
RCLCPP_ERROR_STREAM(this->get_logger(), "Failed to open file for writing.");
}
cpu_usage_.clear();
memory_usage_.clear();
current_time_.clear();
usage_count_ = 0;
++launch_count_;
}
void kill_process(const std::string& process_name) {
std::string command = "ps aux | grep " + process_name + " | grep -v grep | awk '{print $2}'";
std::shared_ptr<FILE> pipe(popen(command.c_str(), "r"), pclose);
if (!pipe) {
RCLCPP_ERROR_STREAM(this->get_logger(), "Failed to run command to find PID.");
return;
}
std::vector<int> pids;
char path[1035];
while (fgets(path, sizeof(path), pipe.get()) != nullptr) {
int pid = std::stoi(path);
pids.push_back(pid);
std::cout << "----------------------------------------------------------" << std::endl;
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"), "Found PID: " << pid);
}
if (pids.empty()) {
RCLCPP_WARN(this->get_logger(), "No matching processes found.");
return;
}
for (int pid : pids) {
if (kill(pid, SIGINT) == 0) {
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"Successfully sent SIGINT (Ctrl+C) to process with PID " << pid);
} else {
RCLCPP_ERROR_STREAM(this->get_logger(),
"Failed to send SIGINT to process with PID " << pid);
}
}
}
void stat_process() {
const char* ros2_launch = "/opt/ros/humble/bin/ros2";
std::string start_launch = "ob_benchmark_" + std::to_string(launch_count_) + ".launch.py";
std::vector<const char*> args = {ros2_launch, "launch", "orbbec_camera", start_launch.c_str(),
nullptr};
pid_t pid = fork();
if (pid == 0) {
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"Child process: launching ros2 launch.");
if (execvp(ros2_launch, (char* const*)args.data()) == -1) {
RCLCPP_ERROR_STREAM(this->get_logger(),
"Failed to execute ros2 launch: " << strerror(errno));
exit(1);
}
} else if (pid > 0) {
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"Parent process: continuing execution.");
} else {
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"), "Fork failed!");
}
}
void functionCallback() {
std::lock_guard<std::mutex> lock(image_mutex_);
// RCLCPP_INFO_STREAM(
// rclcpp::get_logger("ObBenchmark"),
// "get_ps_cpu_usage_by_process: " << get_ps_cpu_usage_by_process(process_name_));
// RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
// "get_top_cpu_usage_by_process: " << get_top_cpu_usage_by_process());
float cpu_usage =
get_ps_cpu_usage_by_process(process_name_) * 0.4 + get_top_cpu_usage_by_process() * 0.6;
float memory_usage = get_memory_usage_by_process();
cpu_usage_.push_back(cpu_usage);
memory_usage_.push_back(memory_usage);
current_time_.push_back(getCurrentTimes());
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"),
"CurrentTimes: " << current_time_[usage_count_]);
RCLCPP_INFO_STREAM(rclcpp::get_logger("ObBenchmark"), "CPU Usage of "
<< process_name_ << ":"
<< cpu_usage_[usage_count_] << "%");
RCLCPP_INFO_STREAM(
rclcpp::get_logger("ObBenchmark"),
"Memory Usage of " << process_name_ << ":" << memory_usage_[usage_count_] << "MB");
usage_count_++;
}
void configCallback() {
std::lock_guard<std::mutex> lock(image_mutex_);
std::string csv = std::string("ob_benchmark/") + std::to_string(launch_count_) + ".csv";
save_to_csv(csv);
kill_process(process_name_);
stat_process();
}
};
} // namespace tools
} // namespace orbbec_camera
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<orbbec_camera::tools::ObBenchmark>());
rclcpp::shutdown();
return 0;
}
+149
View File
@@ -0,0 +1,149 @@
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_components/register_node_macro.hpp>
#include <orbbec_camera/ob_camera_node_driver.h>
#include <orbbec_camera/utils.h>
#include "orbbec_camera_msgs/msg/metadata.hpp"
#include <message_filters/subscriber.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/synchronizer.h>
#include <filesystem>
#include <cpuid.h>
namespace orbbec_camera {
namespace tools {
class StartBenchmark : public rclcpp::Node {
public:
explicit StartBenchmark(const rclcpp::NodeOptions& options) : Node("StartBenchmark", options) {
params_init();
auto custom_qos = rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default));
for (size_t i = 0; i < camera_name_.size(); ++i) {
color_subs_.push_back(this->create_subscription<sensor_msgs::msg::Image>(
color_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::Image> msg) {
this->color_Callback(msg, i);
}));
depth_subs_.push_back(this->create_subscription<sensor_msgs::msg::Image>(
depth_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::Image> msg) {
this->depth_Callback(msg, i);
}));
left_ir_subs_.push_back(this->create_subscription<sensor_msgs::msg::Image>(
left_ir_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::Image> msg) {
this->left_ir_Callback(msg, i);
}));
right_ir_subs_.push_back(this->create_subscription<sensor_msgs::msg::Image>(
right_ir_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::Image> msg) {
this->right_ir_Callback(msg, i);
}));
depth_point_cloud_subs_.push_back(this->create_subscription<sensor_msgs::msg::PointCloud2>(
depth_point_cloud_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::PointCloud2> msg) {
this->depth_point_cloud_Callback(msg, i);
}));
color_point_cloud_subs_.push_back(this->create_subscription<sensor_msgs::msg::PointCloud2>(
color_point_cloud_topics_[i], custom_qos,
[this, i](std::shared_ptr<const sensor_msgs::msg::PointCloud2> msg) {
this->color_point_cloud_Callback(msg, i);
}));
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"), color_topics_[i] << " is subed ");
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"), depth_topics_[i] << " is subed ");
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"), left_ir_topics_[i] << " is subed ");
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"), right_ir_topics_[i] << " is subed ");
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"),
depth_point_cloud_topics_[i] << " is subed ");
RCLCPP_INFO_STREAM(rclcpp::get_logger("StartBenchmark"),
color_point_cloud_topics_[i] << " is subed ");
}
}
private:
std::vector<rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr> color_subs_;
std::vector<rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr> depth_subs_;
std::vector<rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr> left_ir_subs_;
std::vector<rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr> right_ir_subs_;
std::vector<rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr>
depth_point_cloud_subs_;
std::vector<rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr>
color_point_cloud_subs_;
std::vector<std::string> camera_name_;
std::vector<std::string> color_topics_;
std::vector<std::string> depth_topics_;
std::vector<std::string> left_ir_topics_;
std::vector<std::string> right_ir_topics_;
std::vector<std::string> depth_point_cloud_topics_;
std::vector<std::string> color_point_cloud_topics_;
std::mutex image_mutex_;
void params_init() {
std::ifstream file(
"install/orbbec_camera/share/orbbec_camera/config/tools/startbenchmark/"
"start_benchmark_params.json");
if (!file.is_open()) {
RCLCPP_ERROR_STREAM(this->get_logger(), "Failed to open JSON file.");
return;
}
nlohmann::json json_data;
file >> json_data;
camera_name_ =
json_data["start_benchmark_params"]["camera_name"].get<std::vector<std::string>>();
color_topics_.resize(camera_name_.size());
depth_topics_.resize(camera_name_.size());
left_ir_topics_.resize(camera_name_.size());
right_ir_topics_.resize(camera_name_.size());
depth_point_cloud_topics_.resize(camera_name_.size());
color_point_cloud_topics_.resize(camera_name_.size());
for (size_t i = 0; i < camera_name_.size(); ++i) {
color_topics_[i] = "/" + camera_name_[i] + "/color/image_raw";
depth_topics_[i] = "/" + camera_name_[i] + "/depth/image_raw";
left_ir_topics_[i] = "/" + camera_name_[i] + "/left_ir/image_raw";
right_ir_topics_[i] = "/" + camera_name_[i] + "/right_ir/image_raw";
depth_point_cloud_topics_[i] = "/" + camera_name_[i] + "/depth/points";
color_point_cloud_topics_[i] = "/" + camera_name_[i] + "/depth_registered/points";
}
}
void color_Callback(std::shared_ptr<const sensor_msgs::msg::Image> msg, size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->step << "color is subed " << index << "is subed");
}
void depth_Callback(std::shared_ptr<const sensor_msgs::msg::Image> msg, size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->step << "depth is subed " << index << "is subed");
}
void left_ir_Callback(std::shared_ptr<const sensor_msgs::msg::Image> msg, size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->step << "left_ir is subed " << index << "is subed");
}
void right_ir_Callback(std::shared_ptr<const sensor_msgs::msg::Image> msg, size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->step << "right_ir is subed " << index << "is subed");
}
void depth_point_cloud_Callback(std::shared_ptr<const sensor_msgs::msg::PointCloud2> msg,
size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(
rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->point_step << "depth_point_cloud is subed " << index << "is subed");
}
void color_point_cloud_Callback(std::shared_ptr<const sensor_msgs::msg::PointCloud2> msg,
size_t index) {
std::lock_guard<std::mutex> lock(image_mutex_);
RCLCPP_DEBUG_STREAM(
rclcpp::get_logger("StartBenchmark"),
"time is : " << msg->point_step << "color_point_cloud is subed " << index << "is subed");
}
};
} // namespace tools
} // namespace orbbec_camera
RCLCPP_COMPONENTS_REGISTER_NODE(orbbec_camera::tools::StartBenchmark)