diff --git a/.gitignore b/.gitignore
index cb3d6897..f0ca0d45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -764,6 +764,7 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
+
### VisualStudio Patch ###
# Additional files built by Visual Studio
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 7c2789d0..00000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,79 +0,0 @@
-{
- "files.associations": {
- "*.tcc": "cpp",
- "deque": "cpp",
- "forward_list": "cpp",
- "list": "cpp",
- "string": "cpp",
- "vector": "cpp",
- "valarray": "cpp",
- "array": "cpp",
- "string_view": "cpp",
- "chrono": "cpp",
- "cctype": "cpp",
- "clocale": "cpp",
- "cmath": "cpp",
- "csignal": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "any": "cpp",
- "atomic": "cpp",
- "bit": "cpp",
- "bitset": "cpp",
- "cinttypes": "cpp",
- "codecvt": "cpp",
- "compare": "cpp",
- "complex": "cpp",
- "concepts": "cpp",
- "condition_variable": "cpp",
- "cstdint": "cpp",
- "map": "cpp",
- "set": "cpp",
- "unordered_map": "cpp",
- "unordered_set": "cpp",
- "exception": "cpp",
- "algorithm": "cpp",
- "functional": "cpp",
- "iterator": "cpp",
- "memory": "cpp",
- "memory_resource": "cpp",
- "numeric": "cpp",
- "optional": "cpp",
- "random": "cpp",
- "ratio": "cpp",
- "regex": "cpp",
- "system_error": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "utility": "cpp",
- "fstream": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "iosfwd": "cpp",
- "iostream": "cpp",
- "istream": "cpp",
- "limits": "cpp",
- "mutex": "cpp",
- "new": "cpp",
- "numbers": "cpp",
- "ostream": "cpp",
- "semaphore": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "stop_token": "cpp",
- "streambuf": "cpp",
- "thread": "cpp",
- "typeindex": "cpp",
- "typeinfo": "cpp",
- "variant": "cpp",
- "*.ipp": "cpp",
- "filesystem": "cpp",
- "shared_mutex": "cpp"
- }
-}
\ No newline at end of file
diff --git a/README.MD b/README.MD
index 3894d1a4..ca5371e2 100644
--- a/README.MD
+++ b/README.MD
@@ -1,10 +1,8 @@
# OrbbecSDK ROS2 Wrapper v2
- [](http://github.com/badges/stability-badges) 
-
> [!IMPORTANT]
>
-> Welcome to the OrbbecSDK ROS2 Wrapper v2. Before you begin using this version of ROS2 wrapper, it's crucial to check the following device support list to verify the compatibility.
+> Welcome to the OrbbecSDK ROS2 Wrapper v2. Before you begin using this version of ROS2 wrapper, it's crucial to check the following [device support list](#supported-devices) to verify the compatibility.
OrbbecSDK ROS2 Wrapper provides seamless integration of Orbbec cameras with ROS 2 environment. It supports ROS2 Foxy, Humble, and Jazzy distributions.
@@ -125,6 +123,10 @@ Here is the device support list of main branch (v1.x) and v2-main branch (v2.x):
4. not supported: we will not support specific device in this version;
5. to be supported: we will add support in the near future.
+**Documentation Note:**
+
+The following instructions are only applicable to traditional launch files. If you want to experience our latest launch file format, please refer to the following link:
+
## Table of Contents
- [OrbbecSDK ROS2 Wrapper v2](#orbbecsdk-ros2-wrapper-v2)
@@ -203,7 +205,8 @@ Install deb dependencies
```bash
# assume you have sourced ROS environment, same blow
sudo apt install libgflags-dev nlohmann-json3-dev \
-ros-$ROS_DISTRO-image-transport ros-$ROS_DISTRO-image-publisher ros-$ROS_DISTRO-camera-info-manager \
+ros-$ROS_DISTRO-image-transport ros-${ROS_DISTRO}-image-transport-plugins ros-${ROS_DISTRO}-compressed-image-transport \
+ros-$ROS_DISTRO-image-publisher ros-$ROS_DISTRO-camera-info-manager \
ros-$ROS_DISTRO-diagnostic-updater ros-$ROS_DISTRO-diagnostic-msgs ros-$ROS_DISTRO-statistics-msgs \
ros-$ROS_DISTRO-backward-ros libdw-dev
```
@@ -353,12 +356,7 @@ ros2 launch orbbec_camera gemini_intra_process_demo_launch.py
## Use V4L2 backend
-To enable the V4L2 backend for the Gemini2 series cameras, follow these steps:
-
-1. The Gemini2 series cameras support the V4L2 backend.
-2. Open the `config/OrbbecSDKConfig_v2.0.xml` file.
-3. Set the navigation option to `LinuxUVCBackend`.
-4. Change the backend setting to `V4L2`.
+[Setting uvc_backend](#launch-parameters)
Note: The V4L2 backend is not enabled by default.
@@ -370,6 +368,8 @@ The following are the launch parameters available:
a longer time to initialize and reopening the device immediately can cause firmware crashes when hot plugging.
- `enable_point_cloud`: Enables the point cloud.
- `enable_colored_point_cloud`: Enables the RGB point cloud.
+- `cloud_frame_id`:Modifying the frame_id name within the ros message.
+- `ordered_pc`:Enable filtering of invalid point clouds.
- `point_cloud_qos`, `[color|depth|ir]_qos`, `[color|depth|ir]_camera_info_qos`: ROS 2 Message Quality of Service (QoS)
settings. The possible values
are `SYSTEM_DEFAULT`, `DEFAULT`, `PARAMETER_EVENTS`, `SERVICES_DEFAULT`, `PARAMETERS`, `SENSOR_DATA` and are
@@ -378,6 +378,7 @@ The following are the launch parameters available:
and `SENSOR_DATA`, respectively.
- `enable_d2c_viewer`: Publishes the D2C overlay image (for testing only).
- `device_num`: The number of devices. This must be filled in if multiple cameras are required.
+- `uvc_backend`:Optional values: v4l2, libuvc
- `color_width`, `color_height`, `color_fps`: The resolution and frame rate of the color stream.
- `ir_width`, `ir_height`, `ir_fps`: The resolution and frame rate of the IR stream.
- `depth_width`, `depth_height`, `depth_fps`: The resolution and frame rate of the depth stream.
@@ -407,8 +408,6 @@ The following are the launch parameters available:
filtering configuration file is located in the /config/depthfilter directory. Supported only on Gemini2.
- `depth_precision`: The depth precision should be in the format `1mm`. The default value is `1mm`.
- `enable_laser`: Enables the laser. The default value is `true`.
-- `laser_on_off_mode`: Laser on/off alternate mode, 0: off, 1: on-off alternate, 2: off-on alternate. The default value
- is `0`.
- `device_preset`: The default value is `Default`. Only the G330 series is supported. For more information, refer to
the [G330 documentation](https://www.orbbec.com/docs/g330-use-depth-presets/). Please refer to the table below to set
the `device_preset` value based on your use case. The value should be one of the preset names
@@ -452,6 +451,7 @@ The following are the launch parameters available:
- `interleave_frame_enable` : Whether to enable interleave frame mode.
- `interleave_skip_enable` : Whether to enable skip frames.
- `interleave_skip_index` : Set skip pattern IR or flood IR.
+- `[hdr|laser]_index[0|1]_[laser_control|depth_exposure|depth_gain|ir_brightness|ae_max_exposure]`:In interleave frame mode, set the 0th and 1st frame parameters of hdr or laser interleaving frames
**IMPORTANT**: *Please carefully read the instructions regarding software filtering settings
at [this link](https://www.orbbec.com/docs/g330-use-depth-post-processing-blocks/). If you are uncertain, do not modify
@@ -463,7 +463,7 @@ these settings.*
* Imagine we are standing behind of the camera, and looking forward.
* Always use this point of view when talking about coordinates, left vs right IRs, position of sensor, etc..
-
+
* ROS2 Coordinate System: (X: Forward, Y:Left, Z: Up)
* Camera Optical Coordinate System: (X: Right, Y: Down, Z: Forward)
@@ -472,9 +472,9 @@ these settings.*
## Camera sensor structure
-
+
-
+
## TF from coordinate A to coordinate B:
@@ -490,7 +490,7 @@ Example of static TFs of RGB sensor and right infra sensor of Gemini335 module a
ros2 launch orbbec_description view_model.launch.py model:=gemini_335_336.urdf.xacro
```
-
+
## Predefined presets
diff --git a/docs/fastdds_tuning.md b/docs/fastdds_tuning.md
new file mode 100644
index 00000000..1e1ad021
--- /dev/null
+++ b/docs/fastdds_tuning.md
@@ -0,0 +1,154 @@
+# Fast DDS Optimization for Orbbec Camera with ROS2
+
+When operating with the default configuration, Fast DDS exhibits suboptimal transmission efficiency, resulting in
+significant image transmission delays when used with the Orbbec camera in ROS2. This document provides guidance on
+optimizing Fast DDS to enhance image transfer efficiency.
+
+## 1. Adjusting System Parameters
+
+### IP Fragmentation Time
+
+- **Path**: `/proc/sys/net/ipv4/ipfrag_time` (default: 30 seconds)
+- **Purpose**: Defines the duration that IP fragments are kept in memory.
+- **Adjustment**: Decrease this value to reduce the time window where no fragments are received, which can help reduce
+ delays. Consider the specific needs of your environment as this setting affects all incoming fragments.
+
+ **Example**: Set to 3 seconds.
+
+ ```bash
+ sudo sysctl net.ipv4.ipfrag_time=3
+ ```
+
+### IP Fragmentation Memory Threshold
+
+- **Path**: `/proc/sys/net/ipv4/ipfrag_high_thresh` (default: 262144 bytes)
+- **Purpose**: Sets the maximum memory used to reassemble IP fragments.
+- **Adjustment**: Increase this value to allow more memory for fragment reassembly, which can improve handling of larger
+ data packets.
+
+ **Example**: Increase to 128 MB.
+
+ ```bash
+ sudo sysctl net.ipv4.ipfrag_high_thresh=134217728
+ ```
+
+### Maximum Buffer Sizes
+
+- **Purpose**: Configures the maximum buffer sizes for receiving and sending data, which is critical for high-throughput
+ data transmission.
+- **Adjustment**: Set the maximum buffer sizes for both receiving and sending operations.
+
+ **Commands**:
+
+ ```bash
+ sudo sysctl -w net.core.rmem_max=2147483647
+ sudo sysctl -w net.core.rmem_default=2147483647
+ sudo sysctl -w net.core.wmem_max=2147483647
+ sudo sysctl -w net.core.wmem_default=2147483647
+ ```
+
+Alternatively, make these settings permanent by adding them to the `/etc/sysctl.d/10-fastrtps-max.conf` file.
+
+```bash
+sudo gedit /etc/sysctl.d/10-fastrtps-max.conf
+```
+
+add blow lines to the file:
+
+```bash
+net.core.rmem_max=2147483647
+net.core.rmem_default=2147483647
+net.core.wmem_max=2147483647
+net.core.wmem_default=2147483647
+```
+
+then save and exit the file. run `sudo sysctl -p` to apply the changes.
+
+For detailed guidance, refer
+to [ROS 2 DDS Tuning Documentation](https://docs.ros.org/en/foxy/How-To-Guides/DDS-tuning.html).
+
+## 2. Fast DDS Configuration
+
+Below is an example of a Fast DDS configuration file optimized for ROS2 usage with the Orbbec camera. This configuration
+enhances the overall data transmission by adjusting buffer sizes and transport settings.
+
+### Configuration File: `shm_fastdds.xml`
+
+Place this file in the `$HOME` directory.
+
+```xml
+
+
+
+
+ UDP_transport
+ UDPv4
+ 10
+ 65000
+ 1048576
+ 1048576
+
+
+
+
+ profile_for_ros2_context
+
+ UDP_transport
+
+ false
+ 1048576
+ 1048576
+
+
+
+
+ 127.0.0.1
+
+
+
+
+
+
+
+
+
+ ASYNCHRONOUS
+
+
+
+ 0
+ 1000000
+
+
+
+ PREALLOCATED_WITH_REALLOC
+
+
+
+
+ AUTOMATIC
+
+
+
+ 0
+ 1000000
+
+
+
+ PREALLOCATED_WITH_REALLOC
+
+
+```
+
+### Environment Variables
+
+Set the following environment variables to use the custom Fast DDS profile:
+
+```bash
+export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
+export FASTRTPS_DEFAULT_PROFILES_FILE=$HOME/shm_fastdds.xml
+export RMW_FASTRTPS_USE_QOS_FROM_XML=1
+```
+
+This configuration aims to optimize the data flow and reduce transmission delays, improving the responsiveness and
+reliability of the Orbbec camera system in a ROS2 environment.
diff --git a/orbbec_camera/config/camera_params.yaml b/orbbec_camera/config/camera_params.yaml
index 47100b10..7a614316 100644
--- a/orbbec_camera/config/camera_params.yaml
+++ b/orbbec_camera/config/camera_params.yaml
@@ -1,14 +1,14 @@
# common params
depth_registration: false
+depth_registration: false
+enable_d2c_viewer: false
enable_point_cloud: false
enable_colored_point_cloud: false
device_preset: "High Accuracy"
laser_on_off_mode: 0 # 0: off, 1: on-off, 1: off-on
time_domain: "global" # global, device, system
-enable_sync_host_time: true
+enable_sync_host_time: false
frames_per_trigger: 1
-log_level: "warning"
-enable_laser: false
# When 3D reconstruction mode is enabled:
# - The laser will switch to on-off mode
@@ -54,3 +54,5 @@ right_ir_height: 360
right_ir_fps: 60
right_ir_format: "Y8"
right_ir_qos: "sensor_data"
+
+
diff --git a/orbbec_camera/include/orbbec_camera/ob_camera_node.h b/orbbec_camera/include/orbbec_camera/ob_camera_node.h
index 42c0303e..6c624aaa 100644
--- a/orbbec_camera/include/orbbec_camera/ob_camera_node.h
+++ b/orbbec_camera/include/orbbec_camera/ob_camera_node.h
@@ -390,7 +390,7 @@ class OBCameraNode {
std::unique_ptr imuPipeline_ = nullptr;
std::atomic_bool pipeline_started_{false};
std::string camera_name_ = "camera";
- const std::string imu_optical_frame_id_ = "camera_gyro_optical_frame";
+ std::string accel_gyro_frame_id_ = "camera_accel_gyro_optical_frame";
const std::string imu_frame_id_ = "camera_gyro_frame";
std::shared_ptr pipeline_config_ = nullptr;
std::map> sensors_;
diff --git a/orbbec_camera/launch/gemini_330_series.launch.py b/orbbec_camera/launch/gemini_330_series.launch.py
index e42bfb02..565205a9 100644
--- a/orbbec_camera/launch/gemini_330_series.launch.py
+++ b/orbbec_camera/launch/gemini_330_series.launch.py
@@ -168,7 +168,7 @@ def generate_launch_description():
DeclareLaunchArgument('laser_energy_level', default_value='-1'),
DeclareLaunchArgument('enable_3d_reconstruction_mode', default_value='false'),
DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
- DeclareLaunchArgument('time_domain', default_value='device'),
+ DeclareLaunchArgument('time_domain', default_value='global'),
DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
DeclareLaunchArgument('config_file_path', default_value=''),
DeclareLaunchArgument('enable_heartbeat', default_value='false'),
diff --git a/orbbec_camera/src/ob_camera_node.cpp b/orbbec_camera/src/ob_camera_node.cpp
index 24a5337f..99999475 100644
--- a/orbbec_camera/src/ob_camera_node.cpp
+++ b/orbbec_camera/src/ob_camera_node.cpp
@@ -1133,6 +1133,8 @@ void OBCameraNode::getParameters() {
depth_aligned_frame_id_[stream_index] = optical_frame_id_[COLOR];
}
+ accel_gyro_frame_id_ = camera_name_ + "_accel_gyro_optical_frame";
+
setAndGetNodeParameter(enable_sync_output_accel_gyro_, "enable_sync_output_accel_gyro", false);
for (const auto &stream_index : HID_STREAMS) {
std::string param_name = stream_name_[stream_index] + "_qos";
@@ -1156,7 +1158,6 @@ void OBCameraNode::getParameters() {
depth_aligned_frame_id_[stream_index] =
camera_name_ + "_" + stream_name_[COLOR] + "_optical_frame";
}
-
setAndGetNodeParameter(publish_tf_, "publish_tf", true);
setAndGetNodeParameter(tf_publish_rate_, "tf_publish_rate", 0.0);
setAndGetNodeParameter(depth_registration_, "depth_registration", false);
@@ -2428,26 +2429,34 @@ void OBCameraNode::onNewIMUFrameSyncOutputCallback(const std::shared_ptras();
+
auto gyro_info = createIMUInfo(GYRO);
gyro_info.header = imu_msg.header;
- gyro_info.header.frame_id = imu_optical_frame_id_;
imu_info_publishers_[GYRO]->publish(gyro_info);
+
+ auto accel_info = createIMUInfo(ACCEL);
+ imu_msg.header.frame_id = optical_frame_id_[ACCEL];
+ accel_info.header = imu_msg.header;
+ imu_info_publishers_[ACCEL]->publish(accel_info);
+
+ imu_msg.header.frame_id = accel_gyro_frame_id_;
+
+ auto gyro_frame = gryoframe->as();
auto gyroData = gyro_frame->getValue();
imu_msg.angular_velocity.x = gyroData.x - gyro_info.bias[0];
imu_msg.angular_velocity.y = gyroData.y - gyro_info.bias[1];
imu_msg.angular_velocity.z = gyroData.z - gyro_info.bias[2];
+
auto accel_frame = accelframe->as();
auto accelData = accel_frame->getValue();
- auto accel_info = createIMUInfo(ACCEL);
imu_msg.linear_acceleration.x = accelData.x - accel_info.bias[0];
imu_msg.linear_acceleration.y = accelData.y - accel_info.bias[1];
imu_msg.linear_acceleration.z = accelData.z - accel_info.bias[2];
- imu_info_publishers_[ACCEL]->publish(accel_info);
+
imu_gyro_accel_publisher_->publish(imu_msg);
}
@@ -2469,14 +2478,15 @@ void OBCameraNode::onNewIMUFrameCallback(const std::shared_ptr &frame
}
auto imu_msg = sensor_msgs::msg::Imu();
setDefaultIMUMessage(imu_msg);
+
imu_msg.header.frame_id = optical_frame_id_[stream_index];
auto timestamp = fromUsToROSTime(frame->getTimeStampUs());
-
imu_msg.header.stamp = timestamp;
+
auto imu_info = createIMUInfo(stream_index);
imu_info.header = imu_msg.header;
- imu_info.header.frame_id = imu_optical_frame_id_;
imu_info_publishers_[stream_index]->publish(imu_info);
+
if (frame->getType() == OB_FRAME_GYRO) {
auto gyro_frame = frame->as();
auto data = gyro_frame->getValue();
@@ -2501,7 +2511,7 @@ void OBCameraNode::setDefaultIMUMessage(sensor_msgs::msg::Imu &imu_msg) {
imu_msg.orientation.x = 0.0;
imu_msg.orientation.y = 0.0;
imu_msg.orientation.z = 0.0;
- imu_msg.orientation.w = 0.0;
+ imu_msg.orientation.w = 1.0;
imu_msg.orientation_covariance = {-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
imu_msg.linear_acceleration_covariance = {
@@ -2885,7 +2895,7 @@ orbbec_camera_msgs::msg::IMUInfo OBCameraNode::createIMUInfo(
orbbec_camera_msgs::msg::IMUInfo imu_info;
imu_info.header.frame_id = optical_frame_id_[stream_index];
imu_info.header.stamp = node_->now();
- auto imu_profile = stream_profile_[stream_index];
+
if (stream_index == GYRO) {
auto gyro_profile = stream_profile_[stream_index]->as();
auto gyro_intrinsics = gyro_profile->getIntrinsic();
diff --git a/orbbec_camera/src/ob_camera_node_driver.cpp b/orbbec_camera/src/ob_camera_node_driver.cpp
index 7c31cf7b..562b4e6f 100644
--- a/orbbec_camera/src/ob_camera_node_driver.cpp
+++ b/orbbec_camera/src/ob_camera_node_driver.cpp
@@ -439,11 +439,6 @@ void OBCameraNodeDriver::initializeDevice(const std::shared_ptr &dev
if (enable_sync_host_time_ && !isOpenNIDevice(device_info_->pid())) {
TRY_EXECUTE_BLOCK(device_->timerSyncWithHost());
- sync_host_time_timer_ = this->create_wall_timer(std::chrono::seconds(60 * 60 * 2), [this]() {
- if (device_) {
- TRY_EXECUTE_BLOCK(device_->timerSyncWithHost());
- }
- });
}
RCLCPP_INFO_STREAM(logger_, "Device " << device_info_->getName() << " connected");