feat(gemini2): add OrbbecSDK_ROS2/

This commit is contained in:
X-lanni
2025-07-04 15:30:11 +08:00
parent 5cf886315d
commit 1e82e0115a
185 changed files with 864328 additions and 0 deletions
@@ -0,0 +1,111 @@
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0501", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Bootloader Device"
# UVC Modules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0635", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0638", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-w"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0668", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-live"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0636", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0637", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+s"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0536", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+_rgb"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0537", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra+s_rgb"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0669", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto-mega"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="066b", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Femto Bolt"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0660", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra 2"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0670", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 2"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0671", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 2 XL"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0673", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 2 L"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0675", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 2 VL"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0800", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 335"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0801", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 330"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0802", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini dm330"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0803", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 336"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0804", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 335L"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0805", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 330L"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0806", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini dm330L"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0807", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 336L"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080b", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 335Lg"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080d", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 336Lg"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="080e", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 335Le"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0810", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 336Le"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0674", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Orbbec Gemini 2 I"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="0701", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Dabai DCL"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2bc5", ATTRS{idProduct}=="069d", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="Astra Pro2"
# OpenNI Modules
SUBSYSTEM=="usb", ATTR{idProduct}=="0401", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra"
SUBSYSTEM=="usb", ATTR{idProduct}=="0402", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_s"
SUBSYSTEM=="usb", ATTR{idProduct}=="0403", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_pro"
SUBSYSTEM=="usb", ATTR{idProduct}=="0404", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini"
SUBSYSTEM=="usb", ATTR{idProduct}=="0407", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_s"
SUBSYSTEM=="usb", ATTR{idProduct}=="0601", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_NH_GLST"
SUBSYSTEM=="usb", ATTR{idProduct}=="060b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="deeyea"
SUBSYSTEM=="usb", ATTR{idProduct}=="050b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="deeyea_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="060e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel"
SUBSYSTEM=="usb", ATTR{idProduct}=="050e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="060f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astro_pro_plus"
SUBSYSTEM=="usb", ATTR{idProduct}=="050f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astro_pro_plus_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0610", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="bus_cl"
SUBSYSTEM=="usb", ATTR{idProduct}=="0603", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="atlas"
SUBSYSTEM=="usb", ATTR{idProduct}=="0510", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="atlas_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0614", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini"
SUBSYSTEM=="usb", ATTR{idProduct}=="0511", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0616", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u1s"
SUBSYSTEM=="usb", ATTR{idProduct}=="0516", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u1s_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0617", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="projector"
SUBSYSTEM=="usb", ATTR{idProduct}=="0517", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="projector_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0618", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="butterfly"
SUBSYSTEM=="usb", ATTR{idProduct}=="0518", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="butterfly_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="061b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pavo"
SUBSYSTEM=="usb", ATTR{idProduct}=="051b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pavo_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="062b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_pro"
SUBSYSTEM=="usb", ATTR{idProduct}=="052b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_pro_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="062c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_plus"
SUBSYSTEM=="usb", ATTR{idProduct}=="052c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="petrel_plus_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="062d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="pictor"
SUBSYSTEM=="usb", ATTR{idProduct}=="0632", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+"
SUBSYSTEM=="usb", ATTR{idProduct}=="0532", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0633", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+s"
SUBSYSTEM=="usb", ATTR{idProduct}=="0533", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra+s_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0634", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_petal_b"
SUBSYSTEM=="usb", ATTR{idProduct}=="0534", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_petal_b_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0635", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="femto"
SUBSYSTEM=="usb", ATTR{idProduct}=="0636", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis"
SUBSYSTEM=="usb", ATTR{idProduct}=="0536", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0637", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis+s"
SUBSYSTEM=="usb", ATTR{idProduct}=="0537", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="jarvis+s_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0638", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="femto_w"
SUBSYSTEM=="usb", ATTR{idProduct}=="0639", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="argus"
SUBSYSTEM=="usb", ATTR{idProduct}=="0539", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="argus_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="063a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="u2"
SUBSYSTEM=="usb", ATTR{idProduct}=="0650", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth"
SUBSYSTEM=="usb", ATTR{idProduct}=="0651", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth"
SUBSYSTEM=="usb", ATTR{idProduct}=="0654", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="qi_long_zhu"
SUBSYSTEM=="usb", ATTR{idProduct}=="0554", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="qi_long_zhu_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0655", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_plus"
SUBSYSTEM=="usb", ATTR{idProduct}=="0656", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_mini"
SUBSYSTEM=="usb", ATTR{idProduct}=="0657", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1"
SUBSYSTEM=="usb", ATTR{idProduct}=="0557", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0658", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_d1"
SUBSYSTEM=="usb", ATTR{idProduct}=="0657", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1"
SUBSYSTEM=="usb", ATTR{idProduct}=="0557", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dc1_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="0659", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw"
SUBSYSTEM=="usb", ATTR{idProduct}=="0559", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="065a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dw"
SUBSYSTEM=="usb", ATTR{idProduct}=="065b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_pro"
SUBSYSTEM=="usb", ATTR{idProduct}=="065c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e"
SUBSYSTEM=="usb", ATTR{idProduct}=="055c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="065d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_e_lite"
SUBSYSTEM=="usb", ATTR{idProduct}=="065e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_s_pro"
SUBSYSTEM=="usb", ATTR{idProduct}=="0698", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="j1"
SUBSYSTEM=="usb", ATTR{idProduct}=="069c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="TB2201"
SUBSYSTEM=="usb", ATTR{idProduct}=="06a0", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw2"
SUBSYSTEM=="usb", ATTR{idProduct}=="0561", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dcw2_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="069f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_dw2"
SUBSYSTEM=="usb", ATTR{idProduct}=="069a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max"
SUBSYSTEM=="usb", ATTR{idProduct}=="069e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max_pro"
SUBSYSTEM=="usb", ATTR{idProduct}=="0560", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_max_pro_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="06aa", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_gemini_uw"
SUBSYSTEM=="usb", ATTR{idProduct}=="05aa", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="dabai_gemini_uw_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="06a6", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew"
SUBSYSTEM=="usb", ATTR{idProduct}=="05a6", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew_rgb"
SUBSYSTEM=="usb", ATTR{idProduct}=="06a7", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="gemini_ew_lite"
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
source /opt/ros/galactic/setup.bash
ros2 topic echo --qos-durability=transient_local /camera/extrinsic/depth_to_color --qos-profile=services_default
@@ -0,0 +1,111 @@
#!/bin/bash
# Define the vendor ID for Orbbec devices
VID="2bc5"
# Function to get USB port for a given serial number
get_usb_port() {
local serial=$1
for dev in /sys/bus/usb/devices/*; do
if [ -e "$dev/idVendor" ]; then
vid=$(cat "$dev/idVendor")
if [ "$vid" == "${VID}" ]; then
dev_serial=$(cat "$dev/serial" 2>/dev/null)
if [ "$dev_serial" == "$serial" ]; then
echo $(basename $dev)
return
fi
fi
fi
done
echo "Unknown"
}
# Get USB ports for each camera
front_port=$(get_usb_port "CP3S34D00051") # primary camera
rear_port=$(get_usb_port "CP3L44P00047") # secondary-synced camera
left_port=$(get_usb_port "CP3L44P0005Y") # secondary-synced camera
right_port=$(get_usb_port "CP3L44P00054") # secondary-synced camera
# Generate the launch file
cat << EOF > multi_camera_synced.launch.py
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, GroupAction, TimerAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from ament_index_python.packages import get_package_share_directory
import os
def generate_launch_description():
package_dir = get_package_share_directory('orbbec_camera')
launch_file_dir = os.path.join(package_dir, 'launch')
config_file_dir = os.path.join(package_dir, 'config')
config_file_path = os.path.join(config_file_dir, 'camera_params.yaml')
front_camera = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
),
launch_arguments={
'camera_name': 'front_camera',
'usb_port': '$front_port',
'device_num': '4',
'sync_mode': 'software_triggering',
'config_file_path': config_file_path
}.items()
)
rear_camera = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
),
launch_arguments={
'camera_name': 'rear_camera',
'usb_port': '$rear_port',
'device_num': '4',
'sync_mode': 'hardware_triggering',
'config_file_path': config_file_path
}.items()
)
left_camera = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
),
launch_arguments={
'camera_name': 'left_camera',
'usb_port': '$left_port',
'device_num': '4',
'sync_mode': 'hardware_triggering',
'config_file_path': config_file_path
}.items()
)
right_camera = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_file_dir, 'gemini_330_series.launch.py')
),
launch_arguments={
'camera_name': 'right_camera',
'usb_port': '$right_port',
'device_num': '4',
'sync_mode': 'hardware_triggering',
'config_file_path': config_file_path
}.items()
)
ld = LaunchDescription([
GroupAction([rear_camera]),
GroupAction([left_camera]),
GroupAction([right_camera]),
TimerAction(period=3.0, actions=[GroupAction([front_camera])]), # The primary camera should be launched at last
])
return ld
EOF
echo "Launch file 'multi_camera_synced.launch.py' has been generated."
@@ -0,0 +1,115 @@
import os
import shutil
import re
from collections import defaultdict
image_directory = "/home/orbbec/image/"
time_diff_threshold = 100
sync_time_diff_threshold = 33
current_path = os.path.dirname(os.path.abspath(__file__))
master_camera_serial_no = None
use_device_time = True
time_domain = "system_timestamp" if not use_device_time else "hardware_timestamp"
def image_hash(image_info):
assert image_info is not None
return (
f"{image_info['serial_no']}_{image_info['index']}_{image_info['stream_name']}"
)
def parse_image_filename(filename):
parts = filename.split("_")
return {
"stream_name": parts[0],
"index": int(parts[1]),
"system_timestamp": float(parts[2]),
"hardware_timestamp": float(parts[3]),
"resolution": parts[4],
"fps": int(parts[5].split("hz")[0]),
}
def analyze_images():
serial_dirs = [
os.path.join(image_directory, d) for d in os.listdir(image_directory)
]
images = defaultdict(list)
for serial_dir in serial_dirs:
for filename in os.listdir(serial_dir):
if filename.endswith(".png"):
image_info = parse_image_filename(filename)
image_info["serial_no"] = os.path.basename(serial_dir)
image_info["path"] = os.path.join(serial_dir, filename)
images[image_info["serial_no"]].append(image_info)
return images
def copy_images_to_grouped_directory(image_group, index, grouped_image_directory):
if len(image_group) <= 1:
return
ref_image = image_group[0]
for image in image_group:
time_diff = int(image[time_domain] - ref_image[time_domain])
origin_filename = re.split(r"\.", os.path.basename(image["path"]))[0]
suffix = (
"_ref"
if image["serial_no"] == ref_image["serial_no"]
and image["stream_name"] == "color"
else ""
)
status = "_anomaly" if abs(time_diff) > sync_time_diff_threshold else ""
grouped_image_path = os.path.join(
grouped_image_directory,
f"{index}_{origin_filename}_{image['serial_no']}_[{time_diff}]{suffix}{status}.png",
)
shutil.copy(image["path"], grouped_image_path)
def group_images_by_time(all_images):
grouped_image_directory = os.path.join(current_path, "grouped_images")
os.makedirs(grouped_image_directory, exist_ok=True)
reference_serial_no = master_camera_serial_no or list(all_images.keys())[0]
reference_images = [
img for img in all_images[reference_serial_no] if img["stream_name"] == "color"
]
reference_images.sort(key=lambda x: int(x[time_domain]))
for index, ref_image in enumerate(reference_images):
image_group = [ref_image]
for serial_no, images_list in all_images.items():
min_diffs = {name: float("inf") for name in ["color", "depth"]}
min_images = {name: None for name in ["color", "depth"]}
for image in images_list:
if serial_no == reference_serial_no and image["stream_name"] == "color":
continue
time_diff = float(abs(image[time_domain] - ref_image[time_domain]))
stream_name = image["stream_name"]
if time_diff < min_diffs[stream_name]:
min_diffs[stream_name] = time_diff
min_images[stream_name] = image
for stream_name, min_image in min_images.items():
if min_image:
image_group.append(min_image)
copy_images_to_grouped_directory(image_group, index, grouped_image_directory)
def main():
images = analyze_images()
group_images_by_time(images)
if __name__ == "__main__":
main()
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
# Check if user is root/running with sudo
if [ "$(whoami)" != root ]; then
echo Please run this script with sudo
exit
fi
CURR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
if [ "$(uname -s)" != "Darwin" ]; then
# Install UDEV rules for USB device
cp "${CURR_DIR}"/99-obsensor-libusb.rules /etc/udev/rules.d/99-obsensor-libusb.rules
echo "usb rules file install at /etc/udev/rules.d/99-obsensor-libusb.rules"
fi
echo "reload udev rules"
udevadm control --reload-rules && udevadm trigger
echo "udev rules reload done"
echo "exit"
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
VID="2bc5"
for dev in /sys/bus/usb/devices/*; do
if [ -e "$dev/idVendor" ]; then
vid=$(cat "$dev/idVendor")
if [ "$vid" == "${VID}" ]; then
port=$(basename $dev)
product=$(cat "$dev/product" 2>/dev/null) # product name
serial=$(cat "$dev/serial" 2>/dev/null) # serial number
echo "Found Orbbec device $product, usb port $port, serial number $serial"
fi
fi
done
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
executable_filename="component_container"
while true; do
pids=$(pgrep -f "${executable_filename}")
if [ -z "$pids" ]; then
echo "The process ${executable_filename} is not running."
else
for pid in $pids; do
fd_count=$(lsof -p "${pid}" 2>/dev/null | wc -l)
echo "File descriptor count for process ${executable_filename} (${pid}): ${fd_count}"
done
fi
sleep 1
done
@@ -0,0 +1,55 @@
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
def process_data(data):
# 处理数据,将含有 "ms" 的数据转换为浮点数
for col in ['min', 'avg', 'max']:
data[col] = data[col].str.replace(' ms', '').astype(float)
return data
def split_data(data):
# 分别筛选出age和period的数据
age_data = data[data['message_type'] == 'age']
period_data = data[data['message_type'] == 'period']
return age_data, period_data
def plot_data(data, title, y_ticks):
plt.figure(figsize=(12, 6))
for col, color in zip(['min', 'avg', 'max'], ['green', 'yellow', 'cyan']):
# Convert datetime to numpy array
x = data['_time'].to_numpy()
y = data[col].to_numpy()
plt.plot(x, y, label=col, color=color, marker='o', linestyle='-')
plt.ylabel('Milliseconds')
plt.title(title)
plt.gca().xaxis.set_major_locator(mdates.MinuteLocator(interval=10))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
plt.legend()
plt.grid(True, which='both')
plt.xticks(rotation=45)
plt.yticks(range(0, y_ticks[1], y_ticks[0]))
plt.tight_layout()
plt.show()
def main():
plt.style.use('dark_background')
data = pd.read_csv('statistics.csv')
data['_time'] = pd.to_datetime(data['_time'])
data = process_data(data)
age_data, period_data = split_data(data)
plot_data(age_data, 'Message Age', (100, 501))
plot_data(period_data, 'Message Period', (20, 101))
if __name__ == "__main__":
main()
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env python3
from sensor_msgs.msg import PointCloud2
from rclpy.qos import qos_profile_sensor_data
import rclpy
from rclpy.node import Node
class TestNode(Node):
def __init__(self):
super().__init__("test_node")
self.subscription = self.create_subscription(
PointCloud2, "/camera/depth/points", self.listener_callback, qos_profile_sensor_data
)
def listener_callback(self, msg):
pass
def main(args=None):
rclpy.init(args=args)
test_node = TestNode()
rclpy.spin(test_node)
# Destroy the node explicitly
# (optional - otherwise it will be done automatically
# when the garbage collector destroys the node object)
test_node.destroy_node()
rclpy.shutdown()
if __name__ == "__main__":
main()
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
source /opt/ros/galactic/setup.bash
ros2 service call /camera_01/save_images std_srvs/srv/Empty "{}"
ros2 service call /camera_02/save_images std_srvs/srv/Empty "{}"
ros2 service call /camera_03/save_images std_srvs/srv/Empty "{}"
ros2 service call /camera_04/save_images std_srvs/srv/Empty "{}"
ros2 service call /camera_05/save_images std_srvs/srv/Empty "{}"
wait
@@ -0,0 +1,106 @@
import rclpy
from rclpy.node import Node
from tf2_ros.static_transform_broadcaster import StaticTransformBroadcaster
from geometry_msgs.msg import TransformStamped, Quaternion
import numpy as np
from scipy.spatial.transform import Rotation as R
def rotation_matrix_to_quaternion(rotation_matrix):
r = R.from_matrix(rotation_matrix)
q = r.as_quat()
return Quaternion(x=q[0], y=q[1], z=q[2], w=q[3])
def create_transform(matrix, parent_frame, child_frame):
t = TransformStamped()
t.header.stamp = rclpy.time.Time().to_msg()
t.header.frame_id = parent_frame
t.child_frame_id = child_frame
# Convert translation from mm to m
t.transform.translation.x = matrix[0, 3] / 1000.0
t.transform.translation.y = matrix[1, 3] / 1000.0
t.transform.translation.z = matrix[2, 3] / 1000.0
rotation_matrix = matrix[:3, :3]
q = rotation_matrix_to_quaternion(rotation_matrix)
t.transform.rotation = q
return t
def convert_optical_to_vehicle_frame(optical_transform):
# Conversion matrix from optical frame to vehicle frame
conversion_matrix = np.array([
[ 0, 0, 1, 0],
[-1, 0, 0, 0],
[ 0, -1, 0, 0],
[ 0, 0, 0, 1]
])
return np.linalg.multi_dot([conversion_matrix, optical_transform, np.linalg.inv(conversion_matrix)])
class StaticTransformsPublisher(Node):
def __init__(self):
super().__init__('static_transforms_publisher')
self._broadcaster = StaticTransformBroadcaster(self)
optical_matrices = {
'front_camera_link_to_left_camera_link': np.array([
[-0.0117891, 0.0022117, -0.999928, -27.6039],
[0.0052539, 0.999984, 0.00214988, 0.548432],
[0.999917, -0.00522818, -0.0118005, -125.997],
[0, 0, 0, 1]
]),
'front_camera_link_to_right_camera_link': np.array([
[-0.00612923, -0.00990235, 0.999932, 126.278],
[0.00831223, 0.999916, 0.00995314, -0.0925262],
[-0.999947, 0.00837267, -0.0060464, -31.6458],
[0, 0, 0, 1]
]),
'rear_camera_link_to_right_camera_link': np.array([
[-0.00801505, -0.00150606, 0.999967, 30.108],
[0.0144913, 0.999894, 0.0016221, 1.223],
[-0.999863, 0.0145038, -0.00799237, 125.246],
[0, 0, 0, 1]
])
}
# Convert optical frame matrices to vehicle frame
vehicle_matrices = {k: convert_optical_to_vehicle_frame(v) for k, v in optical_matrices.items()}
transforms = []
transforms.append(create_transform(vehicle_matrices['front_camera_link_to_left_camera_link'], 'front_camera_link', 'left_camera_link'))
transforms.append(create_transform(vehicle_matrices['front_camera_link_to_right_camera_link'], 'front_camera_link', 'right_camera_link'))
# Right to rear camera transform
right_to_rear = vehicle_matrices['rear_camera_link_to_right_camera_link']
# Invert the matrix to get right_camera_link to rear_camera_link
right_to_rear = np.linalg.inv(right_to_rear)
# Apply 180-degree rotation around Z-axis to align coordinate systems
rotation_180 = np.array([
[-1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
right_to_rear = np.dot(right_to_rear, rotation_180)
transforms.append(create_transform(right_to_rear, 'right_camera_link', 'rear_camera_link'))
print("Right to Rear Transform:")
print(right_to_rear)
self._broadcaster.sendTransform(transforms)
def main():
rclpy.init()
node = StaticTransformsPublisher()
rclpy.spin(node)
rclpy.shutdown()
if __name__ == '__main__':
main()