[docs]Update docs

This commit is contained in:
jj
2024-12-18 18:35:58 +08:00
parent eca5beffcc
commit 0fcf1ea16f
152 changed files with 4338 additions and 589 deletions
+51
View File
@@ -0,0 +1,51 @@
.. 这一页是模块目录树
.. image:: ../image/product_h5.png
======================================================
Overview
======================================================
.. image:: http://badges.github.io/stability-badges/dist/stable.svg
.. image:: https://img.shields.io/badge/version-2.0.8-green
-------------------------------------------------------------------
OrbbecSDK_ROS2 is a wrapper for the Orbbec 3D camera that provides seamless integration with the ROS2 environment. It
supports ROS2 Foxy, Humble, Iron, and Jazzy distributions.
OrbbecSDK ROS2 souce code link:
`https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main <https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main>`_
With the major update of the new branch v2-main in October 2024, OrbbecSDK_ROS2 is connected to the open source version of OrbbecSDK v2,
which will make OrbbecSDK_ROS2 more flexible and extensible. This update in v2-main ensures compatibility with all new Orbbec USB products
that comply with the UVC standard. However, OrbbecSDK_ROS2 v2 no longer supports Orbbec's traditional OpenNI protocol devices.
We encourage you to check whether your device is supported by OrbbecSDK_ROS2 v2 and use the new version if supported.
For the usage of orbbecSDK, please refer to the link for more detailed introduction:
OrbbecSDK souce code link:
`https://github.com/orbbec/OrbbecSDK_v2 <https://github.com/orbbec/OrbbecSDK_v2>`_
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
supported_cameras.md
supported_platforms.md
======================================================
.. image:: ../image/product_h1.png
+48
View File
@@ -0,0 +1,48 @@
# Supported cameras
> **Important**
>
> Welcome to the OrbbecSDK ROS2 Wrapper. Before you begin using this version of ROS2 wrapper, it's crucial to check the following device support list 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.
With a major update in October 2024, we release the [OrbbecSDK ROS2 Wrapper v2](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main) connected to the open source [OrbbecSDK v2](https://github.com/orbbec/OrbbecSDK_v2/releases) with enhanced flexibility and extensibility. This update ensures compatibility with all Orbbec USB products adhering to UVC standard. However, it no longer supports Orbbec's traditional OpenNI protocol devices. We strongly encourage you to use the v2-main branch if your device is supported.
Here is the device support list of main branch (v1.x) and v2-main branch (v2.x):
| Product Series | Product | [Branch main](https://github.com/orbbec/OrbbecSDK_ROS2/tree/main) | [Branch v2-main](https://github.com/orbbec/OrbbecSDK_ROS2/tree/v2-main) |
| -------------- | --------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------- |
| Gemini 330 | Gemini 335 | full maintenance | recommended for new designs |
| Gemini 336 | full maintenance | recommended for new designs | |
| Gemini 330 | full maintenance | recommended for new designs | |
| Gemini 335L | full maintenance | recommended for new designs | |
| Gemini 336L | full maintenance | recommended for new designs | |
| Gemini 330L | full maintenance | recommended for new designs | |
| Gemini 335Lg | not supported | recommended for new designs | |
| Gemini 2 | Gemini 2 | full maintenance | recommended for new designs |
| Gemini 2 L | full maintenance | recommended for new designs | |
| Gemini 2 XL | recommended for new designs | to be supported | |
| Femto | Femto Bolt | full maintenance | recommended for new designs |
| Femto Mega | full maintenance | recommended for new designs | |
| Femto Mega I | full maintenance | to be supported | |
| Astra | Astra 2 | full maintenance | recommended for new designs |
| Astra+ | limited maintenance | not supported | |
| Astra Pro Plus | limited maintenance | not supported | |
| Astra Mini | Astra Mini Pro | full maintenance | not supported |
**Note** : If you do not find your device, please contact our FAE or sales representative for help.
**Definition** :
1. recommended for new designs: we will provide full supports with new features, bug fix and performance optimization;
2. full maintenance: we will provide bug fix support;
3. limited maintenance: we will provide critical bug fix support;
4. not supported: we will not support specific device in this version;
5. to be supported: we will add support in the near future.
&nbsp;
- For more product information, please refer to the official website link:[https://www.orbbec.com/products](https://www.orbbec.com/products/)
&nbsp;
+26
View File
@@ -0,0 +1,26 @@
# Supported platforms
&nbsp;
- The verified supported platforms and OS are as follows:
| No. | Platform | CPU | OS | ROS2 |
| --- | ------------------------ | --- | ------------ | -------- |
| 1 | X64 PC | X86 | Ubuntu 20.04 | humble |
| 2 | X64 PC | X86 | Ubuntu 22.04 | humble |
| 3 | X64 PC | X86 | Ubuntu 24.04 | foxy |
| 4 | NVIDIA Jetson Orin Nano | Arm | Ubuntu 20.04 | humble |
| 5 | NVIDIA Jetson Orin NX | Arm | Ubuntu 20.04 | humble |
| 6 | NVIDIA Jetson AGX Orin | Arm | Ubuntu 20.04 | humble |
| 7 | NVIDIA Jetson AGX Orin | Arm | Ubuntu 22.04 | humble |
| 8 | NVIDIA Jetson AGX Xavier | Arm | Ubuntu 20.04 | humble |
| 9 | Qualcomm RB5 | Arm | Ubuntu 20.04 | humble |
| 10 | RK3399 | Arm | Ubuntu 20.04 | humble |
| 11 | RK3588 | Arm | Ubuntu 20.04 | Galactic |
| 12 | RK3588 | Arm | Ubuntu 22.04 | humble |
&nbsp;
&nbsp;
&nbsp;
+23
View File
@@ -0,0 +1,23 @@
![product](../image/product_h2.png)
&nbsp;
# Typical applications
OrbbecSDK_ROS2 is a wrapper for the Orbbec 3D camera that provides seamless integration with the ROS2 environment. It
supports ROS2 Foxy, Humble, and Jazzy distributions.
**Applications scenarios:**
* Depth Sensing
* Object Detection
* Body Tracking
* Positional Tracking
* Geo Tracking
* Spatial Mapping
* Camera Control
* Plane Detection
* Multi Camera Fusion
* [OPDK ![OPDK](../image/opdk_logo.png)](https://www.orbbec.com/opdk/)
&nbsp;
+156
View File
@@ -0,0 +1,156 @@
<!-- docs/source/2_installation/build_the_package.md -->
# Build the package
This section provides a comprehensive guide to installing, compiling, and running the OrbbecSDK_ROS2, covering all necessary steps for setup.
- Table of contents
- [Get source code of OrbbecSDK_ROS2](#get-source-code-of-orbbecsdk-ros2)
- [Install environment](#install-environment)
- [Build project](#build-project)
- [Performance Optimization Suggestions](#Performance Optimization Suggestions)
## Get source code of OrbbecSDK_ROS2
**Get source code from github:** [https://github.com/orbbec/OrbbecSDK_ROS2](https://github.com/orbbec/OrbbecSDK_ROS2)
```bash
mkdir -p ~/ros2_ws/src # Create colcon workspace on your local disk
cd ~/ros2_ws/src
git clone -b v2-main https://github.com/orbbec/OrbbecSDK_ROS2.git #Get source code
```
## Install environment
**Install ROS 2 environment**, refer to the official documentation: [ROS2 installation guide: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html](https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html)
```bash
# Tips: If your ROS2 command does not auto-complete, put the following two lines into your `.bashrc` or `.zshrc`
eval "$(register-python-argcomplete3 ros2)"
eval "$(register-python-argcomplete3 colcon)"
```
**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-diagnostic-updater ros-$ROS_DISTRO-diagnostic-msgs ros-$ROS_DISTRO-statistics-msgs \
ros-$ROS_DISTRO-backward-ros libdw-dev ros-$ROS_DISTRO-image-transport \
ros-$ROS_DISTRO-image-transport-plugins ros-$ROS_DISTRO-compressed-image-transport \
ros-$ROS_DISTRO-rqt-tf-tree -y
```
**Install udev rules:**
```bash
tar -zxvf OrbbecSDK_ROS2_xxx.tar.gz -C ~/ros2_ws/src
cd ~/ros2_ws/src/OrbbecSDK_ROS2/orbbec_camera/scripts
sudo bash install_udev_rules.sh
sudo udevadm control --reload-rules && sudo udevadm trigger
```
## Build project
```bash
cd ~/ros2_ws/
colcon build --event-handlers console_direct+ --cmake-args -DCMAKE_BUILD_TYPE=Release
```
Verify the build results.
[start single camera](../3_start_single_camera/start_single_camera.md)
## Performance Optimization Suggestions
### Optimization of usbfs_memory Parameters in USB Camera
**Increase usbfs_memory_mb Value**
- Increase the `usbfs_memory_mb` value to 128MB (this is a reference value and can be adjusted based on your system’s needs)
by running the following command:
```bash
echo 128 | sudo tee /sys/module/usbcore/parameters/usbfs_memory_mb
```
- To make this change permanent, check [this link](https://github.com/OpenKinect/libfreenect2/issues/807).
There are two ways to persist the configuration: by modifying GRUB or by adding a systemd service.
**by modifying GRUB**
Open /etc/default/grub file,Find and replace
```bash
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
```
with this
```bash
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash usbcore.usbfs_memory_mb=128"
```
Update grub
```bash
$ sudo update-grub
```
Reboot and check
```bash
$ cat /sys/module/usbcore/parameters/usbfs_memory_mb
```
**by adding a systemd service**
Create the `/etc/systemd/system/usbfs-memory.service` file
```bash
sudo vi /etc/systemd/system/usbfs-memory.service
```
Paste the following content into the file:
```bash
[Unit]
Description=Set USBFS memory limit
After=multi-user.target
[Service]
ExecStart=/bin/bash -c 'echo 128 | tee /sys/module/usbcore/parameters/usbfs_memory_mb'
ExecStartPost=/bin/bash -c 'echo "USBFS memory limit set to 128 MB"'
[Install]
WantedBy=multi-user.target
```
Reload the systemd configuration to apply the new service
```bash
sudo systemctl daemon-reload
sudo systemctl enable usbfs-memory.service
sudo systemctl start usbfs-memory.service
```
Verify the service status
```bash
sudo systemctl status usbfs-memory.service
cat /sys/module/usbcore/parameters/usbfs_memory_mb
```
### Optimizing ROS DDS Configuration
**CycloneDDS Tuning**
If you use CycloneDDS, please refer to the [CycloneDDS Tuning](../6_advanced/cyclonedds_tuning.md) file.
The default DDS settings may not be optimal for data transmission. Different DDS settings can have varying performance. For more detailed information, please refer to the [CycloneDDS official website](https://docs.ros.org/en/humble/How-To-Guides/DDS-tuning.html).
**FastDDS Tuning**
If you use FastDDS, please refer to the [FastDDS Tuning](../6_advanced/fastdds_tuning.md) file.
+30
View File
@@ -0,0 +1,30 @@
.. 这一页是模块目录树
.. image:: ../image/product_h5.png
======================================================
Installation
======================================================
This section provides instructions for setting up OrbbecSDK_ROS2, including environment preparation, compilation, installation, and detailed configuration options for customized deployments.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
build_the_package.md
package_description.md
======================================================
.. image:: ../image/product_h1.png
+354
View File
@@ -0,0 +1,354 @@
<!-- docs/source/2_installation/package_description.md -->
# Package description
This section provides a detailed overview of the topics, services, launch scripts, and YAML configuration parameters encompassed within the OrbbecSDK_ROS2 package.
- Table of contents
- [All available topics](#all-available-topics)
- [All available services](#all-available-services)
- [All available launch files](#all-available-launch-files)
- [All available yaml files](#all-available-yaml-files)
- [Coordinate systems](#coordinate-systems)
- [Useful configurations](#useful-configurations)
## All available topics
When orbbec camera starts, it will, by default, publish the following topics:
| No. | Published topics | Type | description |
| --- | :-------------------------------------- | :-------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
| 1 | /camera/color/image_raw | [sensor_msgs/msg/Image] | The color stream image |
| 2 | /camera/color/image_raw/compressed | [sensor_msgs/msg/CompressedImage] | The color stream image compressed |
| 3 | /camera/color/image_raw/compressedDepth | [sensor_msgs/msg/CompressedImage] | |
| 4 | /camera/color/image_raw/theora | [theora_image_transport/msg/Packet] | The color image metadata |
| 5 | /camera/color/metadata | [orbbec_camera_msgs/msg/Metadata] | |
| 6 | /camera/depth/camera_info | [sensor_msgs/msg/CameraInfo] | The depth camera information |
| 7 | /camera/depth/image_raw | [sensor_msgs/msg/Image] | The depth stream image |
| 8 | /camera/depth/image_raw/compressed | [sensor_msgs/msg/CompressedImage] | The depth stream image compressed |
| 9 | /camera/depth/image_raw/compressedDepth | [sensor_msgs/msg/CompressedImage] | |
| 10 | /camera/depth/image_raw/theora | [theora_image_transport/msg/Packet] | |
| 11 | /camera/depth/metadata | [orbbec_camera_msgs/msg/Metadata] | The depth image metadata |
| 12 | /camera/left_ir/camera_info | [sensor_msgs/msg/CameraInfo] | The left_ir camera information |
| 13 | /camera/left_ir/image_raw | [sensor_msgs/msg/Image] | The left ir stream image |
| 14 | /camera/left_ir/metadata | [orbbec_camera_msgs/msg/Metadata] | |
| 15 | /camera/right_ir/camera_info | [sensor_msgs/msg/CameraInfo] | The right_ir camera information |
| 16 | /camera/right_ir/image_raw | [sensor_msgs/msg/Image] | The right ir stream image |
| 17 | /camera/right_ir/metadata | [orbbec_camera_msgs/msg/Metadata] | |
| 18 | /camera/ir/camera_info | [sensor_msgs/msg/CameraInfo] | The ir camera information |
| 19 | /camera/ir/image_raw | [sensor_msgs/msg/Image] | The ir stream image |
| 20 | /camera/depth/points | [sensor_msgs/msg/PointCloud2] | The point cloud, only available when `enable_point_cloud` is `true` |
| 21 | /camera/depth_filter_status | [std_msgs/msg/String] | The depth filter status |
| 22 | /camera/depth_registered/points | [sensor_msgs/msg/PointCloud2] | The colored point cloud, only available when `enable_colored_point_cloud` is `true`. |
| 23 | /camera/depth_to_color | [orbbec_camera_msgs/msg/Extrinsics] | |
| 24 | /camera/depth_to_left_ir | [orbbec_camera_msgs/msg/Extrinsics] | |
| 25 | /camera/depth_to_right_ir | [orbbec_camera_msgs/msg/Extrinsics] | |
| 26 | /camera/depth_to_accel | [orbbec_camera_msgs/msg/Extrinsics] | |
| 27 | /camera/depth_to_gyro | [orbbec_camera_msgs/msg/Extrinsics] | |
| 28 | /camera/gyro/imu_info | [orbbec_camera_msgs/msg/IMUInfo] | The imu information |
| 29 | /camera/gyro_accel/sample | [sensor_msgs/msg/Imu] | Synchronized data stream of acceleration and gyroscope,`enable_sync_output_accel_gyro` `turned on` |
| 30 | /clicked_point | [geometry_msgs/msg/PointStamped] | |
| 31 | /diagnostics | [diagnostic_msgs/msg/DiagnosticArray] | The diagnostic information of the camera, Currently, the diagnostic information only includes the temperature of the camera. |
| 32 | /goal_pose | [geometry_msgs/msg/PoseStamped] | |
| 33 | /initialpose | [geometry_msgs/msg/PoseWithCovarianceStamped] | |
| 34 | /parameter_events | [rcl_interfaces/msg/ParameterEvent] | |
| 35 | /rosout | [rcl_interfaces/msg/Log] 8 | |
| 36 | /tf | [tf2_msgs/msg/TFMessage] | |
| 37 | /tf_static | [tf2_msgs/msg/TFMessage] | |
## All available services
The name of the following services already expresses its function.
However, it should be noted that the corresponding `set_[ir|depth|color]*`
and `get[ir|depth|color]*` **services are only available if you set** `enable[ir|depth|color]` to `true` in the stream that corresponds to the argument of the launch file.
Servies can be called like this:
```bash
# Get device info
ros2 service call /camera/get_device_info orbbec_camera_msgs/srv/GetDeviceInfo '{}'
# Get SDK version
ros2 service call /camera/get_sdk_version orbbec_camera_msgs/srv/GetString '{}'
# Set auto exposure
ros2 service call /camera/set_color_auto_exposure std_srvs/srv/SetBool '{data: false}'
# Save point cloud
ros2 service call /camera/save_point_cloud std_srvs/srv/Empty "{}"
```
| No. | Service | type | description |
| --- | :------------------------------- | :------------------------------------- | :-------------------------- |
| 1 | /camera/get_auto_white_balance | [orbbec_camera_msgs/srv/GetInt32] | Get auto white balance |
| 2 | /camera/get_color_exposure | [orbbec_camera_msgs/srv/GetInt32] | Get color exposure |
| 3 | /camera/get_color_gain | [orbbec_camera_msgs/srv/GetInt32] | Get color gain |
| 4 | /camera/get_depth_exposure | [orbbec_camera_msgs/srv/GetInt32] | Get depth exposure |
| 5 | /camera/get_depth_gain | [orbbec_camera_msgs/srv/GetInt32] | Get depth information |
| 6 | /camera/get_device_info | [orbbec_camera_msgs/srv/GetDeviceInfo] | Get device information |
| 7 | /camera/get_ldp_measure_distance | [orbbec_camera_msgs/srv/GetInt32] | Get ldp distance |
| 8 | /camera/get_ldp_status | [orbbec_camera_msgs/srv/GetBool] | Get ldp status |
| 9 | /camera/get_sdk_version | [orbbec_camera_msgs/srv/GetString] | Get sdk version |
| 10 | /camera/get_white_balance | [orbbec_camera_msgs/srv/GetInt32] | Get white balance |
| 11 | /camera/reboot_device | [std_srvs/srv/Empty] | Reboot device |
| 12 | /camera/save_images | [std_srvs/srv/Empty] | Save images |
| 13 | /camera/save_point_cloud | [std_srvs/srv/Empty] | Save point cloud |
| 14 | /camera/set_auto_white_balance | [std_srvs/srv/SetBool] | Set auto white balance |
| 15 | /camera/set_color_auto_exposure | [std_srvs/srv/SetBool] | Set color auto exposure |
| 16 | /camera/set_color_exposure | [orbbec_camera_msgs/srv/SetInt32] | Set color exposure |
| 17 | /camera/set_color_gain | [orbbec_camera_msgs/srv/SetInt32] | Set color gain |
| 18 | /camera/set_color_mirror | [std_srvs/srv/SetBool] | Set color mirror |
| 19 | /camera/set_depth_auto_exposure | [std_srvs/srv/SetBool] | Set depth auto exposure |
| 20 | /camera/set_depth_exposure | [orbbec_camera_msgs/srv/SetInt32] | Set depth exposure |
| 21 | /camera/set_depth_gain | [orbbec_camera_msgs/srv/SetInt32] | Set depth gain |
| 22 | /camera/set_depth_mirror | [std_srvs/srv/SetBool] | Set depth mirror |
| 23 | /camera/set_fan_work_mode | [orbbec_camera_msgs/srv/SetInt32] | Set fan work mode |
| 24 | /camera/set_floor_enable | [std_srvs/srv/SetBool] | Set floor enable |
| 25 | /camera/set_ir_long_exposure | [std_srvs/srv/SetBool] | Set ir long exposure |
| 26 | /camera/set_laser_enable | [std_srvs/srv/SetBool] | Set laser enable |
| 27 | /camera/set_ldp_enable | [std_srvs/srv/SetBool] | Set ldp enable |
| 28 | /camera/set_white_balance | [orbbec_camera_msgs/srv/SetInt32] | Set white balance |
| 29 | /camera/switch_ir | [orbbec_camera_msgs/srv/SetString] | switch left ir and right ir |
| 30 | /camera/toggle_color | [std_srvs/srv/SetBool] | Toggle color |
| 31 | /camera/toggle_depth | [std_srvs/srv/SetBool] | Toggle depth |
## All available launch files
| launch file list | description |
| ---------------------------- | ------------------------------------------------- |
| orbbec_camera.launch.py | Generic ros launch script for a 3D camera product |
| orbbec_multicamera.launch.py | Multicamera devices startup example script |
**Run Command:**
**1. Launch Script for Specifying Device Type:**
The `orbbec_camera.launch.py` supports two optional input parameters: camera_model and config_file_path.
```bash
ros2 launch orbbec_camera orbbec_camera.launch.py camera_model:=gemini330_series
```
or
```bash
# default startup script
ros2 launch orbbec_camera orbbec_camera.launch.py config_file_path:=gemini330_series.yaml
```
**Note:**
**camera_model:**
* The value of the camera_model parameter is the product type corresponding to the camera product being used.
**config_file_path:**
* The YAML configuration file located in the `config/` directory is used. By default, `gemini330_series.yaml` is selected.
* The value of the config_file_path parameter is the path to the yaml configuration file corresponding to the camera product being used.
* Supports the transmission of both absolute paths and relative paths to the config, or YAML files under the config can be specified without a path.
* Supports use intra-process communication. config param use_intra_process_comms: true
**2.multicamera launch:**
The multicamera startup
```bash
ros2 launch orbbec_camera orbbec_multicamera.launch.py
```
or
```bash
ros2 launch orbbec_camera orbbec_multicamera.launch.py config_file_path:=multicamera.yaml
```
**Note:**
1. Multiple devices default config reference config/multicamera.yaml
2. Multiple cameras synced config reference config/multicamera_synced.yaml
## All available yaml files
| product serials | yaml file | description |
| :--------------- | :-------------------- | :------------------------------------- |
| astra2 | astra2.yaml | astra2 camera default params |
| femto | femto.yaml | femto camera default params |
| femtomega | femtomega.yaml | femtomega camera default params |
| femtobolt | femtobolt.yaml | femtobolt camera default params |
| gemini2 | gemini2.yaml | gemini2 camera default params |
| gemini2L | gemini2L.yaml | gemini2L camera default params |
| gemini330 series | gemini330_series.yaml | gemini330_series camera default params |
*All yaml files are fundamentally similar, with the primary differences being the default parameter values set for various models within the same series.
Differences in USB standards, such as USB 2.0 versus USB 3.0, may require parameter adjustments. In case of startup issues, please refer to the specification manual carefully. Pay particular attention to resolution settings and other parameters in the YAML file to ensure compatibility and optimal performance.*
Relationship Between Product yaml Configuration File and common.yaml Configuration File, and a Rough Flowchart of Their Invocation Process
![1733983846554](../image/yaml-config.png)
**yaml Configuration Instructions:**
1.common.yaml
Contains all basic default parameters and common default values.
2.product xxx.yaml
The yaml corresponding to a specific product, such as gemini2.yaml, will configure its product-specific difference parameters and default values based on common.yaml.
3.yaml Loading order description:
Orbbec_camera.launch.py When started, it will load first.commcon.yaml. Reload the corresponding product yaml. For example gemini2.yaml The same parameter value will overwrite the corresponding default parameter value in common.yaml.
**Launch Startup Instructions:**
1.orbbec_camera.launch.py Command line parameters have the highest priority. That is, parameters carried in the command line will override the default values of the same parameters in the yaml file.
2.orbbec_multicamera.launch.py The command line configuration corresponds to multicamera.yaml or multicamera_synced.yaml. For multi-machine yaml configuration, you can refer to the modification guide to modify the multi-machine configuration.
## Coordinate systems
### ROS2(Robot) vs Optical(Camera) coordination systems
* Point Of View:
* 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 and Camera Coordinate System](../image/image7.png)
* ROS2 Coordinate System: (X: Forward, Y:Left, Z: Up)
* Camera Optical Coordinate System: (X: Right, Y: Down, Z: Forward)
* All data published in our wrapper topics is optical data taken directly from our camera sensors.
* static and dynamic TF topics publish optical CS and ROS CS to give the user the ability to move from one CS to other CS.
### Camera sensor structure
![module in rviz2](../image/image9.png)
![module in rviz2](../image/image10.png)
### TF from coordinate A to coordinate B:
In Orbbec cameras, the origin point (0,0,0) is taken from the camera_link position
Our wrapper provide static TFs between each sensor coordinate to the camera base (camera_link)
Also, it provides TFs from each sensor ROS coordinates to its corrosponding optical coordinates.
Example of static TFs of RGB sensor and right infra sensor of Gemini335 module as it shown in rviz2:
```bash
ros2 launch orbbec_description view_model.launch.py model:=gemini_335_336.urdf.xacro
```
![module in rviz2](../image/image8.png)
## Useful configurations
### 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`.
Note: The V4L2 backend is not enabled by default.
Config V4L2 in `config/OrbbecSDKConfig_v2.0.xml` file.
```
<!-- Default configuration of data streams for different types of devices -->
<Device>
<!-- Whether to enumerate network devices, bool type, true-enable, false-disable (default) -->
<EnumerateNetDevice>false</EnumerateNetDevice>
<!-- Global UVC Backend select on Linux; optional values: Auto, V4L2, LibUVC; The default
setting is "Auto," which will automatically select the appropriate option based on the
system's capabilities and the device's speciality. -->
<LinuxUVCBackend>Auto</LinuxUVCBackend>
<FemtoMega>
<!-- For Femto-Mega devices, it must be set to V4L2, LibUVC is not supported -->
<LinuxUVCDefaultBackend>V4L2</LinuxUVCDefaultBackend>
```
### Predefined presets
| Preset | Features | Recommended use cases |
| :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Default | - Best visual perception - Overall good performance in accuracy, fill rate, tiny objects, etc. | - Generic - Robotics |
| Hand | - Clear hand and finger edges | - Gesture recognition |
| High Accuracy | - Depth of high confidence - Barely noise depth values - Lower fill rate | - Collision avoidance - Object scanning |
| High Density | - Higher fill rate - More tiny objects - May suffer from noise depth values | - Object recognition - Pick & place - Foreground & background animation |
| Medium Density | - Balanced performance in fill rate and accuracy - In comparison to Default: lower fill rate, better edge quality | - Generic and alternative to Default |
| Custom | - User defined Preset - Derived from Presets above, with customized modifications, e.g. a new configuration for the post-processing pipeline, modified mean intensity set point of depth AE function, etc. | - Better depth performance achieved using customized configurations in comparison to using predefined presets<br /> - For well-established custom configurations |
Choose the appropriate preset name based on your specific use case and set it as the value for the `device_preset`
parameter.
### Depth work mode switch
OrbbecSDK_ROS2 supports the depth work mode switch. The depth work mode switch is supported by Gemini 2, Gemini 2 L,
and Femto and Femto Bolt cameras.
- Before starting the camera, depth work mode (depth_work_mode) can be configured for the corresponding xxx.launch.py
file's support.
- The depth work mode switch is supported by Gemini 2, Gemini 2 L, and Gemini 2 XL cameras.
- The default depth work mode configuration of xxx.launch.py is the camera's default configuration. If you need to
modify it, you can switch to the corresponding mode as needed.
- The specific camera depth work mode support types can be found in the comments of the depth mode.
```python
# Depth work mode support is as follows:
# Unbinned Dense Default
# Unbinned Sparse Default
# Binned Sparse Default
# Obstacle Avoidance
DeclareLaunchArgument('depth_work_mode', default_value='')
```
- View depth work modes:
```bash
ros2 run orbbec_camera list_depth_work_mode_node
```
### Configuration of depth NFOV and WFOV modes
For the Femto Mega and Femto Bolt devices, the NFOV and WFOV modes are implemented by configuring the resolution of
Depth and IR in the launch file.
In launch file, depth_width、depth_height、ir_width、ir_height represents the resolution of the depth and the resolution of
the IR.
The frame fps and resolution of IR must be consistent with the depth. The correspondence between different modes and
resolutions is as follows:
- NFOV unbinned: 640 x 576.
- NFOV binned: 320 x 288.
- WFOV unbinned: 1024 x 1024.
- WFOV binned: 512 x 512.
### Network device enumeration
Currently, the network device enumeration function is supported only by the Femto Mega device. When accessing this
device over the network, if `enumerate_net_device` is set to `true`, the device will be automatically enumerated,
eliminating the need to configure the IP address in advance or set the enable switch to true. The specific configuration
methods are as follows:
- `enumerate_net_device`: enumeration network device automatically, only supported by Femto Mega.
if `enumerate_net_device` set to `true`, the device will be enumerated automatically,No need to set
the `net_device_ip`
and `net_device_port` parameters.
- `net_device_ip`: The IP address of the device.
- `net_device_port`: The port number of the device.
### Compressed Image
You can use image_transport to compress the image using jpeg. Below is an example of how to use it:
To access the compressed color image, you can use the following command:
```bash
ros2 topic echo /camera/color/image_raw/compressed --no-arr
```
This command will allow you to receive the compressed color image from the specified topic.
**Note:** The compressed topic for depth is /camera/depth/image_raw/compressedDepth. The compressed topics for color and IR are /camera/color/image_raw/compressed and /camera/ir/image_raw/compressed, respectively.
+31
View File
@@ -0,0 +1,31 @@
.. 这一页是模块目录树
.. .. image:: ../image/product_h7.png
.. image:: ../image/product_h5.png
======================================================
Single camera
======================================================
This guide provides instructions on how to launch the camera node with a colored point cloud feature enabled using ROS 2.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
start_single_camera.md
======================================================
.. image:: ../image/product_h1.png
+145
View File
@@ -0,0 +1,145 @@
<!-- docs/source/3_start_single_camera/start_single_camera.md -->
# Single camera
This guide provides instructions on how to launch the camera node with a colored point cloud feature enabled using ROS 2.
- Table of contents
- [Start single camera](#start-single-camera)
- [Visualizing data in rviz2](#visualizing-data-in-rviz2)
- [Display view topics service](#display-view-topics-service)
- [Example visualizations](#example-visualizations)
- [TF tree diagram](#tf-tree-diagram)
## Start single camera
For how to compile and build methods, please refer to Chapter `Installation/Build_the_package `documentation and follow the steps provided
[build_the_package](../2_installation/build_the_package.md)
- Command to start single camera node
On terminal 1: Launch camera node, example of gemini330 series :
```bash
cd ~/ros2_ws/
source /opt/ros/$ROS_DISTRO/setup.bash
source install/setup.bash
ros2 launch orbbec_camera orbbec_camera.launch.py config_file_path:=gemini330_series.yaml
```
## Visualizing data in rviz2
- view_display launch
`view_display.launch.py` supports loading different `.rviz` files through yaml configuration. For example, loading the default `.rviz` file to display four streams. config in different `.model.yaml `files through yaml configuration.
On terminal 2:
```bash
cd ~/ros2_ws/
source /opt/ros/$ROS_DISTRO/setup.bash
source install/setup.bash
ros2 launch orbbec_description view_display.launch.py camera_model:=gemini335_336
```
![view_display_gemini335_336](../image/view_display_gemini335_336.png)
- view_model launch
`view_model.launch.py` supports loading different `.model.yaml `files through yaml configuration. For example, loading the default model file to display gemini335_336 model .
On terminal 3:
```bash
cd ~/ros2_ws/
source /opt/ros/$ROS_DISTRO/setup.bash
source install/setup.bash
ros2 launch orbbec_description view_model.launch.py camera_model:=gemini335_336
```
![view_model_gemini335_336](../image/view_model_gemini335_336.png)
- Or you can run rviz2 and configure it by yourself
```bash
cd ~/ros2_ws/
source /opt/ros/$ROS_DISTRO/setup.bash
source install/setup.bash
rviz2
```
When runing rviz2, select the topic you wish to visualize from the list of published topics.
Add the selected topic to rviz2 to start viewing the data.
## Display view topic/service/param
Once the camera node is running, it will publish data on several ROS topics. Below is a list of the available topics:
By executing `ros2 topic list`, the following topics are displayed:
On terminal 4:
```bash
ros2 topic list
```
Other , to display services/ parameters , example as follows
```bash
ros2 service list
ros2 param list
```
Get device info:
```bash
ros2 service call /camera/get_device_info orbbec_camera_msgs/srv/GetDeviceInfo '{}'
```
Get SDK version:
```bash
ros2 service call /camera/get_sdk_version orbbec_camera_msgs/srv/GetString '{}'
```
Set auto exposure:
```bash
ros2 service call /camera/set_color_auto_exposure std_srvs/srv/SetBool '{data: false}'
```
Save point cloud:
```bash
ros2 service call /camera/save_point_cloud std_srvs/srv/Empty "{}"
```
&nbsp;
## Example visualizations
Here are examples of how the visualization might appear in rviz2:
- **PointCloud Visualization**
![PointCloud View](../image/image1.jpg)
&nbsp;
- **Image Data Visualization**
![Image Data View](../image/image2.jpg)
&nbsp;
## TF tree diagram
To get the TF tree
```bash
ros2 run rqt_tf_tree rqt_tf_tree --force-discover
```
&nbsp;
The TF tree diagram for the OrbbecSDK_ROS2 is illustrated below:
![single_cam_tf.png](../image/single_cam_tf.png)
+30
View File
@@ -0,0 +1,30 @@
.. 这一页是模块目录树
.. .. image:: ../image/product_h4.png
.. image:: ../image/product_h5.png
======================================================
Multiple cameras
======================================================
This section describes how to configure and use multiple Orbbec cameras simultaneously in a ROS 2 environment.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
start_multi_camera.md
======================================================
.. image:: ../image/product_h1.png
+97
View File
@@ -0,0 +1,97 @@
<!-- docs/source/4_start_multi_camera/start_multi_camera.md -->
# Multiple cameras
This section describes how to configure and use multiple Orbbec cameras simultaneously in a ROS 2 environment.
- Table of contents
- [Script to list connected cameras](#script-to-list-connected-cameras)
- [Setup for multiple camera launch](#setup-for-multiple-camera-launch)
- [Running the launch file](#running-the-launch-file)
- [Configuring the TF tree for multiple cameras](#configuring-the-tf-tree-for-multiple-cameras)
- [Example TF configuration for two cameras](#example-tf-configuration-for-two-cameras)
## List connected cameras
To determine which USB ports the cameras are connected to, you can execute the following command.
This Command lists all Orbbec devices attached to the system along with their USB port and serial number:
```bash
$ ros2 run orbbec_camera list_devices_node
```
As follows:
```
USB port_id: 4-1.1-3
Modified USB port_id: 4-1.1
[INFO]serial: CP7X54P0004D
[INFO]usb port: 4-1.1
[INFO]usb connect type: USB3.2
USB port_id: 4-1.2-5
Modified USB port_id: 4-1.2
[INFO]serial: CP7X54P000AA
[INFO]usb port: 4-1.2
[INFO]usb connect type: USB3.2
```
From the log above, it appears that the two USB cameras you are connected to are using USB ports **4-1.1 and 4-1.2**.
## Setup for multiple camera launch
You can launch multiple cameras by specifying different USB ports for each camera. You can refer to orbbec_multicamera.launch.py to implement the multicamera launch script you need..
## Running the launch file
To execute the launch configuration for multiple cameras, use the command:
```
ros2 launch orbbec_camera orbbec_multicamera.launch.py config_file_path:=multicamera.yaml
```
**Note:**
1. Multiple devices default config reference config/multicamera.yaml
2. Multiple cameras synced config reference config/multicamera_synced.yaml
## Example TF configuration for two cameras
When using multiple cameras, it's essential to calibrate them and publish a static TF tree for each camera. The following Python script configures the TF tree based on your calibration results:
```python
from launch import LaunchDescription
from launch_ros.actions import Node
# Define the extrinsics for each camera (x, y, z, roll, pitch, yaw)
camera_01_transform = ['0.1', '0', '0.2', '0', '0', '1.57'] # Example parameters
camera_02_transform = ['-0.1', '0', '0.2', '0', '0', '-1.57'] # Example parameters
def generate_launch_description():
ld = LaunchDescription([
Node(
package='tf2_ros',
executable='static_transform_publisher',
name='camera_01_tf',
arguments=camera_01_transform + ['base_link', 'camera_01_link'],
output='screen'
),
Node(
package='tf2_ros',
executable='static_transform_publisher',
name='camera_02_tf',
arguments=camera_02_transform + ['base_link', 'camera_02_link'],
output='screen'
)
])
return ld
```
Save this configuration as `multi_camera_tf.launch.py` in the launch directory of the Orbbec camera package. To run it, use:
```bash
ros2 launch orbbec_camera multi_camera_tf.launch.py
```
+35
View File
@@ -0,0 +1,35 @@
.. 这一页是模块目录树
.. .. image:: ../image/product_h9.png
.. image:: ../image/product_h5.png
======================================================
Advanced
======================================================
This section explores the advanced usage of Orbbec SDK ROS2, specifically tailored for product application scenarios. It offers comprehensive guidance on how to fully harness the SDK's capabilities, enabling you to unlock the potential of your robotics projects. Discover the optimal ways to enhance your projects using the cutting-edge features provided by Orbbec SDK ROS2 environments.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
multi_camera_sync.md
component_node.md
zero_copy.md
gdb_debug.md
backward_ros.md
cyclonedds_tuning.md
fastdds_tuning.md
======================================================
.. image:: ../image/product_h1.png
+44
View File
@@ -0,0 +1,44 @@
# Backward ros
To use the `backward_ros` package for debugging your ROS2 project named `OrbbecSDK_ROS2`, you can follow these steps:
## Add `backward_ros` as a dependency:
In your `package.xml`, add `backward_ros` as a dependency:
xml
```
<depend>backward_ros</depend>
```
## Configure `CMakeLists.txt`:
In your `CMakeLists.txt`, find the `backward_ros` package and link it to your executable:
cmake
```
find_package(backward_ros REQUIRED)
include_directories(${backward_INCLUDE_DIRS})
add_executable(your_node src/your_node.cpp)
target_link_libraries(your_node ${backward_LIBRARIES})
```
## Build your project with debug information:
Use `colcon build` with the `RelWithDebInfo` or `Debug` option to ensure that your executable is built with debug information:
```
colcon build --cmake-args '-DCMAKE_BUILD_TYPE=RelWithDebInfo'
```
## Run your node:
After building, you can run your node as you normally would with ROS 2. If your node crashes, `backward_ros` will automatically generate a stack trace with detailed information, including line numbers, to help you debug the issue.
## Example `backward_ros`
When your program crashes, you can go to the Log folder under the workspace to find the stack trace of the crash.
![Multi_camera1](../image/backward_ros.png)
+157
View File
@@ -0,0 +1,157 @@
# Component node
In ROS2, component nodes enable efficient resource management and modularity by allowing multiple nodes to be loaded into a single process, called a component container. Here’s an overview of setting up a component node and adding it to a container, both for a single node and through a `launch.py` file.
### Creating a component node
To define a node as a component, the following steps are required:
1. **Create a node class**: The node class should inherit from `rclcpp::Node` (C++) or `Node` (Python) and implement the core functionalities within it.
2. **Add plugin export**: In `CMakeLists.txt`, export the node as a plugin by adding it to a component library using `rclcpp_components`. For example:
```cmake
# CMakeLists.txt
find_package(rclcpp_components REQUIRED)
add_library(my_component SHARED src/my_component.cpp)
target_link_libraries(my_component PUBLIC rclcpp::rclcpp)
ament_target_dependencies(my_component rclcpp rclcpp_components)
rclcpp_components_register_nodes(my_component "mypackage::MyComponent")
```
3. **Declare the plugin in package.xml**: Add the node as a plugin in the package manifest:
```xml
<export>
<rclcpp_components>
<node plugin="mypackage::MyComponent" />
</rclcpp_components>
</export>
```
### Loading a single node into a component container
To load a node directly into a component container, use the ComponentManager node. Run the command:
```bash
ros2 run rclcpp_components component_container
```
Then load the component into this container with the load_component service:
```bash
ros2 component load /ComponentManager mypackage my_component
```
Replace /ComponentManager with the actual name of your container, if different.
3. Adding Component Nodes via a Launch File
In launch.py, you can define a component container and load nodes into it. Here’s an example launch.py file:
```python
from launch import LaunchDescription
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode
def generate_launch_description():
container = ComposableNodeContainer(
name='my_container',
namespace='',
package='rclcpp_components',
executable='component_container_mt', # use 'component_container' for single-threaded
composable_node_descriptions=[
ComposableNode(
package='mypackage',
plugin='mypackage::MyComponent',
name='my_component'
),
ComposableNode(
package='another_package',
plugin='another_package::AnotherComponent',
name='another_component'
)
],
output='screen',
)
return LaunchDescription([container])
```
**explanation**
- ComposableNodeContainer: This creates a component container to hold nodes. Use component_container_mt for multi-threading or component_container for - single-threaded operation.
- ComposableNode: Specifies each component to load, with arguments for the package name, plugin type, and node name.
- output: Set to 'screen' to display output in the terminal.
Running the Launch File
To run the launch file, use the command:
```bash
ros2 launch mypackage my_launch_file.launch.py
```
This starts the component container and loads the specified nodes into it, enabling efficient component management in ROS2.
### Loading a launch.py into a component container
```python
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.conditions import UnlessCondition
from launch_ros.actions import Node, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
def generate_launch_description():
bringup_dir = os.path.join(get_package_share_directory('mypackage'))
# Define the shared container name
shared_container_name = "shared_nvblox_container"
# Create the shared component container
shared_container = Node(
name=shared_container_name,
package='rclcpp_components',
executable='component_container_mt', # or 'component_container' for single-threaded
output='screen'
)
# Include another launch file to attach nodes to the shared container
orbbec_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource([os.path.join(
bringup_dir, 'launch', 'sensors', 'orbbec.launch.py')]),
launch_arguments={
'attach_to_shared_component_container': 'True',
'component_container_name': shared_container_name
}.items(),
condition=UnlessCondition(LaunchConfiguration('from_bag'))
)
# Declare any required launch arguments
from_bag_arg = DeclareLaunchArgument(
'from_bag',
default_value='false',
description='Condition to use data from a bag file'
)
# Return LaunchDescription with shared container and nodes attached
return LaunchDescription([from_bag_arg, shared_container, orbbec_launch])
```
**Explanation**
- **shared_container_name**: The name of the shared container, which other nodes can reference for attaching.
- **shared_container**: Defines the shared container as a `Node`, using `component_container_mt` for multi-threading. This container will host multiple component nodes.
- **IncludeLaunchDescription**: Loads and attaches nodes from another launch file (in this example, orbbec.launch.py) to the shared container.
- launch_arguments: The arguments passed to the included launch file.
- **attach_to_shared_component_container**: Set to `'True'`, specifying that nodes in `orbbec.launch.py` should be added to the existing shared container.
- **component_container_name**: References the `shared_container_name`, linking nodes from the included launch file to the shared container.
- **condition**: Only includes the `orbbec.launch.py` nodes in the shared container if the `from_bag` parameter is `false`.
**Running the launch File**
Execute the following command to start the launch file:
```
ros2 launch mypackage my_main_launch_file.launch.py
```
This command will start the shared component container and attach the nodes specified in `orbbec.launch.py` to it if the `from_bag` condition is not met.
+56
View File
@@ -0,0 +1,56 @@
# CycloneDDS tuning
● Edit cyclonedds configuration file
```bash
sudo gedit /etc/cyclonedds/config.xml
```
Add
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://cdds.io/confighttps://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
<Domain id="any">
<General>
<NetworkInterfaceAddress>lo</NetworkInterfaceAddress>
<AllowMulticast>false</AllowMulticast>
</General>
<Internal>
<MinimumSocketReceiveBufferSize>16MB</MinimumSocketReceiveBufferSize>
</Internal>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>30</MaxAutoParticipantIndex>
<Peers>
<Peer address="localhost"/>
</Peers>
</Discovery>
</Domain>
</CycloneDDS>
```
● Set the environment variables, add to `.zshrc` or `.bashrc`
```bash
export ROS_DOMAIN_ID=42 # Numbers from 0 to 232
export ROS_LOCALHOST_ONLY=1
export CYCLONEDDS_URI=file:///etc/cyclonedds/config.xml
```
Tips:to understand why the maximum ROS_DOMAIN_ID is 232, please visit [The ROS DOMAIN ID](https://docs.ros.org/en/humble/Concepts/About-Domain-ID.html)
● Increase UDP receive buffer size
Edit
```bash
/etc/sysctl.d/10-cyclone-max.conf
```
Add
```bash
net.core.rmem_max=2147483647
net.core.rmem_default=2147483647
```
+154
View File
@@ -0,0 +1,154 @@
# FastDDS tuning
When operating with the default configuration, FastDDS exhibits suboptimal transmission efficiency, resulting in
significant image transmission delays when used with the Orbbec camera in ROS2. This document provides guidance on
optimizing FastDDS to enhance image transfer efficiency.
## 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. FastDDS configuration
Below is an example of a FastDDS 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
<?xml version="1.0" encoding="UTF-8"?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<transport_descriptors>
<transport_descriptor>
<transport_id>UDP_transport</transport_id>
<type>UDPv4</type>
<maxInitialPeersRange>10</maxInitialPeersRange>
<maxMessageSize>65000</maxMessageSize>
<sendBufferSize>1048576</sendBufferSize>
<receiveBufferSize>1048576</receiveBufferSize>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="participant_profile_ros2" is_default_profile="true">
<rtps>
<name>profile_for_ros2_context</name>
<userTransports>
<transport_id>UDP_transport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
<sendSocketBufferSize>1048576</sendSocketBufferSize>
<listenSocketBufferSize>1048576</listenSocketBufferSize>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>127.0.0.1</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
</rtps>
</participant>
<data_writer profile_name="default publisher profile" is_default_profile="true">
<qos>
<publishMode>
<kind>ASYNCHRONOUS</kind>
</publishMode>
<latencyBudget>
<duration>
<sec>0</sec>
<nanosec>1000000</nanosec>
</duration>
</latencyBudget>
</qos>
<historyMemoryPolicy>PREALLOCATED_WITH_REALLOC</historyMemoryPolicy>
</data_writer>
<data_reader profile_name="default subscription profile" is_default_profile="true">
<qos>
<data_sharing>
<kind>AUTOMATIC</kind>
</data_sharing>
<latencyBudget>
<duration>
<sec>0</sec>
<nanosec>1000000</nanosec>
</duration>
</latencyBudget>
</qos>
<historyMemoryPolicy>PREALLOCATED_WITH_REALLOC</historyMemoryPolicy>
</data_reader>
</profiles>
```
### Environment variables
Set the following environment variables to use the custom FastDDS 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.
+23
View File
@@ -0,0 +1,23 @@
# GDB debug
Debugging ROS 2 programs with GDB involves several steps:
## Config debug
Set `CMAKE_BUILD_TYPE` to `Debug` in ` orbbec_camera/CMakeLists.txt`
```
set(CMAKE_BUILD_TYPE Debug)
```
## Use xterm terminal to open gdb debugging
Install xterm
```bash
sudo apt install xterm
```
Take gemini_330_series.launch.py as an example to use xterm terminal to open gdb
![Multi_camera1](../image/gdb_1.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

+128
View File
@@ -0,0 +1,128 @@
<!-- docs/source/6_advanced/multi_camera_sync.md -->
# Multiple cameras synchronization
- Table of contents
- [Preparation](#preparation)
- [Check the camera usb port](#check-the-camera-usb-port)
- [Configure multi_camera_synced.launch.py](#configure-multi_camera_synced.launch.py)
- [Run multi_camera_synced.launch.py](#run-multi_camera_synced.launch.py)
- [Advanced Parameters](#advanced-parameters)
- [Gmsl example](#gmsl-example)
- [suggestions for multiple cameras synchronization](#suggestions for multiple cameras synchronization)
## Preparation
First, please read the user documentation:[https://www.orbbec.com/docs/set-up-cameras-for-external-synchronization_v1-2/](https://www.orbbec.com/docs/set-up-cameras-for-external-synchronization_v1-2/)
Secondly,make sure the cameras are properly connected to the multi-camera synchronizer
![Multi_camera1](../image/Sync_connect.png)
## Check the camera usb port
```bash
ros2 run orbbec_camera list_devices_node
```
Output:
![Multi_camera1](../image/Multi_camera1.png)
## Configure multiple cameras synced
Open `orbbec_multicamera.launch.py`, the camera configuration is as shown below
You can replace `multicamera.yaml `with other yaml files, such as `multicamera_synced.yaml`
![Multi_camera1](../image/Multi_camera5.png)
Open `multicamera_synced.yaml`,the camera configuration is as shown below
![Multi_camera1](../image/Multi_camera6.png)
```
note: gemini330_series_sync_front_camera.yaml is the camera configuration file.
```
**When configuring multiple cameras sync, you need to pay attention to the following parameters:**
1.**camera_name**
camera_name is set to front_camera, for example, the color image topic name is /front_camera/color/image_raw"
2.**usb_port**
The `usb_port` parameter specifies the USB port number to which the camera is connected. In your example, "2-7" indicates that the camera devices connected to USB ports 2 through 7 are started. You can use the command `ros2 run orbbec_camera list_devices_node` to view the device port numbers.
Please ensure that these port numbers match your actual hardware cameras. If you have more cameras or cameras connected to different ports, you need to configure the corresponding port number for each device.
3.**device_num**
The device_num parameter indicates the number of cameras to be started. Please ensure that this value matches the number of cameras you want to start and does not exceed the number of cameras actually connected or the system's processing capacity.
4.**sync_mode**
sync_mode is set to software_triggering, indicating that the 2-7 camera device is set to software trigger mode, and the selection of multiple cameras synchronization mode can refer to the following table.
Please refer to the[multi-camera synchronization mode definition description](https://www.orbbec.com/docs-general/set-up-cameras-for-external-synchronization_v1-2/#) for details.
![Multi_camera1](../image/Multi_camera7_1.png)
![Multi_camera1](../image/Multi_camera7_2.png)
`multicamera_synced.yaml` describes the camera startup order, the host must be started last
![Multi_camera1](../image/Multi_camera6.png)
## Run `multicamera_synced.launch.py`
```bash
ros2 launch orbbec_camera multicamera_synced.launch.py
```
## Advanced sync parameters
Some camera parameters are related to multi-camera sync
| Camera parameters | action |
| ----------------------- | ------------------------------------------------------------- |
| trigger_out_enabled | Trigger signal switch setting |
| trigger2image_delay_us | Configure the secondarydepth delay and secondarycolor delay |
| trigger_out_delay_us | Trigger signal delay |
| frames_per_trigger | Software trigger frequency(used with software_trigger_period) |
| software_trigger_period | Software trigger interval(used with frames_per_trigger) |
## GMSL camera example
**Key Distinctions Between GMSL and USB Devices:**
**1.usb_port Configuration:**
• For USB cameras, the port is specified as: usb_port: "2-3"
• For GMSL cameras, the port should be designated as: usb_port: "gmsl2-3"
**2.Color Stream Format Compatibility:**
• It is important to note that GMSL devices do not support the MJPG color format. Consequently, the format must be switched to YUYV when utilizing GMSL equipment.
## suggestions for multiple cameras synchronization
When configuring multiple cameras, there are several additional points to consider:
1.Power Supply: Ensure that each camera receives sufficient power supply. Simultaneous operation of multiple high-power devices can put strain on the USB bus.
2.Bandwidth Limitations: Simultaneous data transfer from multiple cameras can strain the USB bus or network bandwidth. Consider using higher bandwidth connections (such as USB 3.0 or higher) or optimizing data transfer settings.
3.Synchronization Issues: If you require time synchronization between multiple cameras, ensure that your system supports and is properly configured for camera synchronization.
4.Software Configuration: In ROS, you may need to configure separate nodes and topics for each camera to ensure they do not conflict. Using namespaces and the parameter server can help manage these configurations.
Finally, do not forget to conduct thorough testing before deployment to ensure that all cameras function correctly and that system performance meets expectations.
+54
View File
@@ -0,0 +1,54 @@
# Zero-copy communications
## Efficient intra-process communication:
[](https://github.com/orbbec/OrbbecSDK_ROS2?tab=readme-ov-file#efficient-intra-process-communication)
Our ROS2 Wrapper node supports zero-copy communications if loaded in the same process as a subscriber node. This can reduce copy times on ../image/pointcloud topics, especially with big frame resolutions and high FPS.
You will need to launch a component container and launch our node as a component together with other component nodes. Further details on "Composing multiple nodes in a single process" can be found [here](https://docs.ros.org/en/rolling/Tutorials/Composition.html).
Further details on efficient intra-process communication can be found [here](https://docs.ros.org/en/humble/Tutorials/Intra-Process-Communication.html#efficient-intra-process-communication).
## Zero-copy example
[](https://github.com/orbbec/OrbbecSDK_ROS2?tab=readme-ov-file#example)
## Manually loading multiple components into the same process
[](https://github.com/orbbec/OrbbecSDK_ROS2?tab=readme-ov-file#manually-loading-multiple-components-into-the-same-process)
* Start the component:
```shell
ros2 run rclcpp_components component_container
```
* Add the wrapper:
```shell
ros2 component load /ComponentManager orbbec_camera orbbec_camera::OBCameraNodeDriver -e use_intra_process_comms:=true
```
Load other component nodes (consumers of the wrapper topics) in the same way.
## Using a launch file
[](https://github.com/orbbec/OrbbecSDK_ROS2?tab=readme-ov-file#using-a-launch-file)
```shell
ros2 launch orbbec_camera orbbec_camera.launch.py use_intra_process_comms:=true
```
```bash
$ ros2 component list
/camera/camera_container
1 /camera/camera
2 /camera/frame_latency
```
## Limitations
[](https://github.com/orbbec/OrbbecSDK_ROS2?tab=readme-ov-file#limitations)
* Node components are currently not supported on RCLPY
* Compressed images using `image_transport` will be disabled as this isn't supported with intra-process communication
+31
View File
@@ -0,0 +1,31 @@
.. 这一页是模块目录树
.. :titlesonly:
.. image:: ../image/product_h5.png
======================================================
Tools
======================================================
This chapter details the tools integrated with Orbbec SDK ROS2 and their usage methods, providing a guide for developers to effectively utilize these functionalities in robotic applications.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
tools.md
======================================================
.. image:: ../image/product_h1.png
+82
View File
@@ -0,0 +1,82 @@
# Some practical tools
| Tool Name | effect |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------- |
| list_devices_node | check the camera USB port number |
| list_depth_work_mode_node | view depth work modes |
| list_camera_profile_mode_node | check which profiles the camera supports |
| topic_statistics_node | topic statistics |
| multi_save_rgbir_node | Multi camera sync save image, used to test synchronization quality |
| metadata_save_files_node | Save the depth, left and right ir images and metadata data |
| metadata_export_files_node | Compared with metadata_save_files_node, it has one more color collection but reduces some metadata data saving |
## list_devices_node
If you have connected multiple cameras, but you want to start a specific camera, you can run the list_devices_node tool to view the USB port of each camera.
```bash
ros2 run orbbec_camera list_devices_node
```
![Multi_camera1](../image/list_devices_node.png)
## list_depth_work_mode_node
OrbbecSDK_ROS2 supports the depth work mode switch. The depth work mode switch is supported by Gemini 2, Gemini 2 L, and Femto and Femto Bolt cameras.
View depth work modes:
```bash
ros2 run orbbec_camera list_depth_work_mode_node
```
![Multi_camera1](../image/list_depth_work_mode_node.png)
## list_camera_profile_mode_node
Check which profiles the camera supports:
```bash
ros2 run orbbec_camera list_camera_profile_mode_node
```
![Multi_camera1](../image/list_camera_profile_mode_node.png)
The above image only shows part of the output
## multi_save_rgbir_node
The purpose of multi_save_rgbir_node is to test the synchronization effect of using multiple Orbbec cameras in OrbbecSDK ROS2
This tool will save the color and left IR images of each camera and the timestamp information
The configuration parameter file of this tool node is multi_save_rgbir_params.json
![Multi_camera1](../image/multi_save_rgbir_node1.png)
* The parameter order of usb_ports: "Host", "Slave 1", "Slave 2", "Slave 3". Fill in as many usb_ports as there are cameras.
* ir_topics and color_topics are topic names. Fill in as many names as there are cameras.
## metadata_save_files_node
The metadata_save_files_node tool will save the depth, left and right IR, images and metadata data
The configuration parameter file of this tool node is metadata_save_params.json
![Multi_camera1](../image/metadata_save_params.png)
```bash
ros2 run orbbec_camera metadata_save_files_node
```
## metadata_export_files_node
The metadata_save_files_node tool will save depth, color, left and right IR images and some metadata data
The configuration parameter file of this tool node is metadata_save_params.json
![Multi_camera1](https://file+.vscode-resource.vscode-cdn.net/home/jj/openSDK/opensdk_ros2/src/OrbbecSDK_ROS2/docs/source/image/metadata_save_params.png)
```bash
ros2 run orbbec_camera metadata_export_files_node
```
+69
View File
@@ -0,0 +1,69 @@
# FAQ
## Unexpected crash
If the camera node crashes unexpectedly, it will generate a crash log in the current running directory: `Log/camera_crash_stack_trace_xx.log`.
Please send this log to the support team or submit it to a GitHub issue for further assistance.
**Regarding logging, please refer to the following log recommendations:**
In ROS, the location of the log directory is typically associated with the ROS workspace, but the specific log path may vary depending on the installation method and operating system.
Here are some common locations for ROS log directories:
1. **Default Global ROS Log Directory** : Global logs are typically recorded in the `~/.ros/log` directory. Here, `~` represents the user's home directory.
2. **Workspace-Specific Log Directories** : In some cases, ROS nodes may log to specific directories within their workspace. This can often be achieved by setting the `ROS_LOG_DIR` environment variable.
For the underlying Orbbec SDK, the log level can be configured via the `log_level` field in the `common.yaml` file.
## How to Quickly Modify the Default Resolution
How to Quickly Modify the Default Resolution, Video Format, and Frame Rate Parameters of a Product?
1.Locate the corresponding product yaml configuration file, such as gemini330_series.yaml, in the orbbec_camera/config directory.
2.Open the corresponding product yaml configuration file, such as gemini330_series.yaml, and modify the resolution, format, and frame rate settings for the video stream.
For example:
![1733990376409](../image/faq_1.png)
3.Compile and Run
```
colcon build --event-handlers console_direct+ --cmake-args -DCMAKE_BUILD_TYPE=Release
source install/setup.bash
ros2 launch orbbec_camera orbbec_camera.launch.py config_file_path:=gemini330_series.yaml
```
## No data stream from multiple cameras
**Insufficient Power Supply**:
- Ensure that each camera is connected to a separate hub.
- Use a powered hub to provide sufficient power to each camera.
**High Resolution**:
- Try lowering the resolution to resolve data stream issues.
**Increase usbfs_memory_mb Value**:
- Increase the `usbfs_memory_mb` value to 128MB (this is a reference value and can be adjusted based on your system’s needs)
by running the following command:
```bash
echo 128 | sudo tee /sys/module/usbcore/parameters/usbfs_memory_mb
```
- To make this change permanent, check [this link](https://github.com/OpenKinect/libfreenect2/issues/807).
## Additional troubleshooting
- If you encounter other issues, set the `log_level` parameter to `debug`. This will generate an SDK log file in the running directory: `Log/OrbbecSDK.log.txt`.
Please provide this file to the support team for further assistance.
- If firmware logs are required, set `enable_heartbeat` to `true` to activate this feature.
## Why are there so many yaml files?
- Different yaml files have varying default resolutions and image formats.
- To simplify usage, each camera has its own yaml file.
+31
View File
@@ -0,0 +1,31 @@
.. 这一页是模块目录树
.. image:: ../image/product_h5.png
======================================================
Help center
======================================================
This section offers insights into common issues encountered during Orbbec SDK ROS2 development, along with their solutions, ensuring smoother progress in robotics projects.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
FAQ.md
issues.md
======================================================
.. image:: ../image/product_h1.png
+5
View File
@@ -0,0 +1,5 @@
# Issue
Regarding issues with OrbbecSDK_ROS 2, please refer to the detailed descriptions on the GitHub issue page for reference:
[https://github.com/orbbec/OrbbecSDK_ROS2/issues](https://github.com/orbbec/OrbbecSDK_ROS2/issues)
+15
View File
@@ -0,0 +1,15 @@
# Purchase link
Purchase channels:
Taobao Direct Enterprise Store:[Click to go to the mall](https://shop142544700.taobao.com/)
JD.com Direct Flagship Store:[Click to go to the mall](https://mall.jd.com/index-1000467272.html)
Gemini2 VL Camera: [Click to purchase on JD.com](https://item.jd.com/100063076495.html)
Official Website Purchase Link:[Click to go to the official product area](https://www.orbbec.com/products)
Gemini2 VL Camera: [Click to purchase on the official website](https://www.orbbec.com/products/stereo-vision-camera/gemini-335l)
G335L Camera: [Click to purchase on the official website](https://www.orbbec.com/products/stereo-vision-camera/gemini-335l)
+12
View File
@@ -0,0 +1,12 @@
# Technical support
Developer Community Technical Support:
Orbbec
Email: [[email protected]](https://file+10-002e8-002e190-002e12.vscode-resource.vscode-cdn.net/guojia/OrbbecSDK_ROS2/docs/source/mailto:[email protected])
3D Vision Developer Community: [developer.orbbec.com.cn/](https://developer.orbbec.com.cn/)
Orbbec Official Website: Chinese: [www.orbbec.com.cn](https://www.orbbec.com.cn/) English: [www.orbbec.com](https://www.orbbec.com/)
Orbbec Official ad
+14
View File
@@ -0,0 +1,14 @@
## OrbbecSDK_ROS2 license
Copyright 2024 Orbbec Ltd.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with
the License. You may obtain a copy of the License at
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "
AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
Other names and brands may be claimed as the property of others
+28
View File
@@ -0,0 +1,28 @@
.. 这一页是模块目录树
.. image:: ../image/product_h5.png
======================================================
License
======================================================
Copyright 2024 Orbbec Ltd.
======================================================
.. toctree::
:maxdepth: 2
:caption: This Section Covers:
license.md
======================================================
.. image:: ../image/product_h1.png
+1115
View File
File diff suppressed because it is too large Load Diff
+135
View File
@@ -0,0 +1,135 @@
/* 让表格自动拉伸到满宽度 */
table {
width: 100%;
margin-left: auto;
margin-right: auto;
}
/* 让表格中的每个 <th> 和 <td> 也自动拉伸 */
th,
td {
width: auto;
}
ul {
width: 100%;
/* 列表宽度占满整个容器 */
}
/* 修改 Sphinx Theme 项目标题的字体大小 Book和rtd 均OK */
.wy-side-nav-search>a {
font-size: 16px;
}
/* 修改项目标题的字体大小 Book和rtd 均OK*/
.wy-side-nav-search>div.version {
font-size: 16px;
}
.sidebar-logo {
width: 500px;
/* 或者使用百分比 */
height: auto;
max-width: 90%;
max-height: 90%;
}
.sidebar-content {
line-height: 1.0;
/* 行间距是字体大小的1.5倍 */
}
.sidebar {
padding: 20px;
/* 内边距 */
margin-bottom: 20px;
/* 外边距 */
}
.sidebar-text {
font-size: 30px;
}
/* 修改侧边栏的背景颜色 */
.wy-nav-side {
background-color: #cecece !important;
}
/* 针对导航栏链接的选择器 */
.wy-nav-side a {
color: #000000;
/* 修改为您需要的颜色 */
}
/* 鼠标悬停位置 hover 和 激活位置active 状态的样式 */
/* .wy-nav-side a:hover {
background-color: #ebebeb !important;
} */
/* .wy-nav-side .current li.toctree-l1 a:hover,
.wy-nav-side .current li.toctree-l2 a:hover,
.wy-nav-side .current li.toctree-l3 a:hover {
background-color: #ebebeb !important;
color: #108bf0 !important;
font-weight: bold !important;
} */
.wy-nav-side .current li[class^="toctree-l"] a:hover {
background-color: #ebebeb !important;
color: #108bf0 !important;
font-weight: bold !important;
}
/* .wy-nav-side .current li[class^="toctree-l"] a:active {
background-color: #ffffff !important;
color: #108bf0 !important;
font-weight: bold !important;
}
*/
/* 当前活动项的颜色 */
.wy-nav-side .current>a {
color: #108bf0 !important;
font-weight: bold !important;
}
h1.wy-banner-title {
color: #0267da !important;
}
/* 如果也需要修改小标题 */
h2.wy-banner-subtitle {
color: #7b7b7b !important;
}
.wy-side-nav-search>a {
color: #ffffff !important;
}
/* 调整最大宽度 OK */
.wy-nav-content {
max-width: 1100px;
}
/* 设置选中标题的背景色 */
.wy-menu-vertical li.current>a {
background-color: #e9e9e9 !important;
/* 你可以选择任何颜色 */
color: #ffffff;
/* 可选:设置选中标题的文本颜色 */
}
/* 设置选中标题下所有子标题(包括二级和三级)的背景色 */
/* .wy-menu-vertical li.current ul li a,
.wy-menu-vertical li.current li.current ul li a {
background-color: #ffffff !important;
} */
.wy-menu-vertical li.toctree-l1.current>ul li.toctree-l2>a,
.wy-menu-vertical li.toctree-l2.current>ul li.toctree-l3>a,
.wy-menu-vertical li.toctree-l3.current>ul li.toctree-l4>a {
background-color: #ffffff ;
}
+34
View File
@@ -0,0 +1,34 @@
// custom.js 可以禁止自动折叠,但不能跳转
// document.addEventListener('DOMContentLoaded', function () {
// // 展开所有侧边栏目录项
// var toctreeItems = document.querySelectorAll('.toctree-l1');
// toctreeItems.forEach(function (item) {
// item.classList.add('current');
// });
// // 监听点击事件,确保点击标题时不会折叠其他标题,并且能够跳转到相应的文档部分
// document.querySelectorAll('.toctree-l1 a').forEach(function (link) {
// link.addEventListener('click', function (event) {
// // 阻止默认的折叠行为
// event.preventDefault();
// // 展开点击的标题
// var parentLi = this.closest('li');
// parentLi.classList.add('current');
// // 移除其他同级目录项的 'current' 类
// parentLi.parentElement.children.forEach(function (sibling) {
// if (sibling !== parentLi) {
// sibling.classList.remove('current');
// }
// });
// // 跳转到相应的文档部分
// var target = this.getAttribute('href');
// if (target.startsWith('#')) {
// document.querySelector(target).scrollIntoView();
// } else {
// // 如果链接不是锚点,则在新窗口或当前窗口打开链接
// window.open(target, '_blank');
// }
// });
// });
// });
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

+53
View File
@@ -0,0 +1,53 @@
<svg width="240" height="45" viewBox="0 0 240 45" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M132.524 33.6127C132.524 33.3717 132.524 33.1909 132.524 33.0252C132.524 26.3818 132.524 19.7534 132.524 13.11C132.524 12.5074 132.524 12.5074 133.097 12.5074C138.4 12.5074 143.717 12.5074 149.02 12.5225C150.692 12.5225 152.319 12.7786 153.871 13.4113C155.016 13.8632 155.995 14.5261 156.793 15.4902C158.571 17.6444 158.36 20.4012 156.281 22.2541C156.025 22.4801 155.769 22.676 155.468 22.932C155.633 23.0676 155.769 23.1731 155.904 23.2936C158.586 25.4478 158.737 28.7921 156.251 31.1723C154.925 32.4377 153.313 33.0855 151.536 33.3566C150.496 33.5224 149.427 33.6127 148.372 33.6278C143.25 33.6579 138.128 33.6429 133.006 33.6429C132.886 33.6127 132.735 33.6127 132.524 33.6127ZM136.727 29.9822C136.953 29.9822 137.134 29.9822 137.33 29.9822C140.96 29.9822 144.606 29.9822 148.237 29.9822C148.915 29.9822 149.607 29.9671 150.285 29.8918C151.265 29.8014 152.199 29.5604 153.027 29.003C153.494 28.6867 153.856 28.2799 153.946 27.6924C154.082 26.8337 153.705 26.1106 152.831 25.6135C151.701 24.9657 150.466 24.7398 149.186 24.7398C146.052 24.7247 142.934 24.7398 139.801 24.7398C139.635 24.7398 139.469 24.7398 139.288 24.7398C139.288 23.5045 139.288 22.3295 139.288 21.1092C139.499 21.1092 139.665 21.1092 139.846 21.1092C142.828 21.1092 145.811 21.1243 148.794 21.0942C149.487 21.0942 150.195 21.049 150.873 20.9134C151.566 20.7628 152.259 20.5519 152.876 20.2204C154.383 19.407 154.368 17.8252 152.892 16.9665C152.575 16.7857 152.244 16.605 151.897 16.5447C150.858 16.379 149.803 16.153 148.749 16.153C144.922 16.1078 141.096 16.138 137.27 16.138C137.104 16.138 136.923 16.153 136.742 16.1681C136.727 20.7628 136.727 25.3273 136.727 29.9822Z" fill="#4A4F54"/>
<path d="M183.849 22.917C184.195 23.2183 184.542 23.4895 184.843 23.8058C186.756 25.7341 186.892 28.4909 185.144 30.5848C183.879 32.0913 182.207 32.9048 180.324 33.2512C179.194 33.4621 178.019 33.5977 176.859 33.5977C171.677 33.6279 166.51 33.6128 161.328 33.6128C161.192 33.6128 161.071 33.5977 160.906 33.5977C160.891 33.417 160.876 33.2362 160.876 33.0705C160.876 26.3969 160.876 19.7384 160.876 13.0649C160.876 12.7787 160.815 12.4924 161.282 12.4924C166.675 12.5075 172.068 12.5075 177.477 12.5226C179.134 12.5226 180.746 12.7937 182.282 13.4114C183.502 13.9085 184.557 14.6466 185.34 15.7162C186.847 17.7349 186.666 20.2205 184.888 21.9981C184.587 22.3145 184.225 22.6007 183.849 22.917ZM165.079 29.9823C165.32 29.9823 165.5 29.9823 165.696 29.9823C169.342 29.9823 173.002 29.9823 176.648 29.9823C177.311 29.9823 177.989 29.9672 178.652 29.8919C179.616 29.8015 180.535 29.5605 181.363 29.0181C182.011 28.5963 182.388 28.0088 182.312 27.1953C182.237 26.3969 181.755 25.9149 181.092 25.5533C179.992 24.9507 178.802 24.7248 177.567 24.7248C174.419 24.7097 171.285 24.7248 168.137 24.7248C167.971 24.7248 167.805 24.7248 167.624 24.7248C167.624 23.4744 167.624 22.2994 167.624 21.0942C167.85 21.0942 168.016 21.0942 168.182 21.0942C171.165 21.0942 174.147 21.1093 177.13 21.0792C177.823 21.0792 178.531 21.0038 179.209 20.8984C180.038 20.7779 180.821 20.5218 181.514 20.0247C182.599 19.2262 182.599 17.9006 181.499 17.1473C181.107 16.8762 180.67 16.6352 180.203 16.5448C179.164 16.3489 178.109 16.1531 177.07 16.138C173.243 16.0928 169.417 16.123 165.591 16.123C165.425 16.123 165.259 16.138 165.064 16.1531C165.079 20.7628 165.079 25.3424 165.079 29.9823Z" fill="#4A4F54"/>
<path d="M122.763 27.3157C124.013 28.4004 125.203 29.4248 126.378 30.4491C127.568 31.4735 128.743 32.4979 130.009 33.5826C129.828 33.6127 129.722 33.6277 129.617 33.6277C127.824 33.6277 126.032 33.6428 124.254 33.6127C124.043 33.6127 123.787 33.4922 123.606 33.3415C121.557 31.5639 119.524 29.7863 117.505 27.9936C117.249 27.7677 116.993 27.6773 116.646 27.6773C114.477 27.6923 112.308 27.6773 110.139 27.6773C109.973 27.6773 109.792 27.6773 109.596 27.6773C109.596 26.4571 109.596 25.282 109.596 24.0468C109.762 24.0468 109.928 24.0468 110.093 24.0468C113.182 24.0468 116.255 24.0468 119.343 24.0468C120.578 24.0468 121.783 23.881 122.913 23.3538C123.998 22.8567 124.841 22.1185 125.067 20.8983C125.384 19.1508 124.811 17.5992 123.064 16.8008C122.16 16.394 121.196 16.1982 120.232 16.1982C115.908 16.168 111.585 16.1831 107.276 16.1831C107.216 16.1831 107.156 16.1982 107.05 16.2132C107.05 21.998 107.05 27.7827 107.05 33.5976C105.634 33.5976 104.279 33.5976 102.893 33.5976C102.893 26.5926 102.893 19.6027 102.893 12.5827C103.013 12.5676 103.134 12.5526 103.239 12.5526C108.738 12.5526 114.236 12.5224 119.735 12.5827C122.115 12.6128 124.39 13.1552 126.453 14.4206C130.219 16.7104 130.732 22.465 127.026 25.3423C125.911 26.216 124.661 26.7885 123.29 27.1651C123.154 27.1952 123.019 27.2404 122.763 27.3157Z" fill="#4A4F54"/>
<path d="M84.7096 33.6128C83.2333 33.6128 81.772 33.673 80.2957 33.5977C77.2979 33.4471 74.6164 32.4679 72.3869 30.404C70.1423 28.3251 69.1179 25.7491 69.133 22.7061C69.148 17.2528 73.0045 14.2851 76.6953 13.1552C78.021 12.7485 79.3919 12.5376 80.7778 12.5376C83.5195 12.5225 86.2763 12.4773 89.018 12.5527C92.0309 12.6431 94.8028 13.5168 97.1077 15.5354C99.1715 17.3432 100.166 19.633 100.286 22.3446C100.572 28.7018 95.8272 32.3323 91.5941 33.2211C90.4793 33.4471 89.3193 33.5224 88.1744 33.5826C87.0145 33.6429 85.8545 33.5977 84.6795 33.5977C84.7096 33.6278 84.7096 33.6128 84.7096 33.6128ZM84.7397 29.9822C86.0654 29.9822 87.3911 29.9973 88.7168 29.9822C89.9972 29.9521 91.2325 29.681 92.3774 29.1085C94.5166 28.0239 95.9176 26.3818 96.1435 23.9414C96.3996 21.2599 95.4355 19.1057 93.1909 17.5842C91.8502 16.6803 90.3588 16.2284 88.762 16.2133C86.0805 16.1681 83.4141 16.1681 80.7326 16.2133C79.0153 16.2435 77.4335 16.7858 76.0174 17.7951C72.402 20.3561 72.3116 26.2312 76.4091 28.7168C77.7197 29.5152 79.1358 29.937 80.6573 29.9822C81.998 30.0124 83.3689 29.9822 84.7397 29.9822Z" fill="#4A4F54"/>
<path d="M189.137 12.5677C196.594 12.5677 204.035 12.5677 211.492 12.5677C211.492 13.7729 211.492 14.9479 211.492 16.1682C205.421 16.1682 199.38 16.1682 193.294 16.1682C193.294 20.7779 193.294 25.3575 193.294 29.9973C199.35 29.9973 205.406 29.9973 211.492 29.9973C211.492 31.2175 211.492 32.3926 211.492 33.5977C204.05 33.5977 196.609 33.5977 189.122 33.5977C189.137 26.5927 189.137 19.5878 189.137 12.5677Z" fill="#4A4F54"/>
<path d="M239.768 12.5677C239.768 13.7879 239.768 14.963 239.768 16.1832C239.572 16.1832 239.407 16.1832 239.226 16.1832C234.752 16.1832 230.263 16.1832 225.788 16.1832C224.237 16.1832 222.761 16.5447 221.42 17.3582C219.115 18.7592 217.955 20.823 218.091 23.5346C218.226 26.3216 219.778 28.1594 222.248 29.2742C223.303 29.7562 224.433 29.9822 225.593 29.9822C230.127 29.9973 234.676 29.9973 239.211 29.9973C239.377 29.9973 239.557 29.9973 239.768 29.9973C239.768 31.2024 239.768 32.3925 239.768 33.5977C239.663 33.6127 239.572 33.6278 239.482 33.6278C234.692 33.6278 229.901 33.7182 225.126 33.5826C221.134 33.4772 217.789 31.8201 215.515 28.4306C212.788 24.3632 212.848 16.7104 220.275 13.5921C221.902 12.9142 223.604 12.5526 225.367 12.5526C230.052 12.5225 234.737 12.5376 239.422 12.5376C239.512 12.5376 239.618 12.5526 239.768 12.5677Z" fill="#4A4F54"/>
<path d="M30.5227 11.5132C31.3965 11.7994 32.3154 12.1308 32.2552 13.2004C32.1949 14.2399 31.276 14.5261 30.3872 14.8123C30.5529 14.8876 30.7186 14.9479 30.8692 15.0232C31.6375 15.3998 31.7731 16.0175 31.2006 16.6502C31.0952 16.7707 30.9747 16.9063 30.9445 17.0419C30.583 18.5031 30.2365 19.9644 29.9804 21.0791C29.8298 20.341 29.6339 19.2262 29.3778 18.1265C29.2423 17.5239 29.1067 16.9213 28.6246 16.4543C28.2329 16.0627 28.3836 15.4902 28.8958 15.1588C29.1217 15.0082 29.3778 14.9178 29.6942 14.7521C28.7602 14.511 27.8563 14.27 27.7509 13.2607C27.6304 12.1158 28.6096 11.8296 29.4381 11.4228C29.2121 11.3626 28.9711 11.3324 28.7602 11.2571C27.7961 10.9408 26.9675 10.4738 26.7416 9.37405C26.621 8.81667 26.8169 8.34967 27.1634 7.92787C27.5852 7.41567 28.1426 7.12945 28.7753 6.94868C28.9259 6.90348 29.0615 6.85829 29.1971 6.70765C29.0012 6.66245 28.7903 6.61726 28.5945 6.57207C27.6605 6.36116 26.8018 5.98455 26.1239 5.27652C25.0092 4.14669 24.9941 2.61012 26.1089 1.46522C27.9768 -0.463032 31.9237 -0.49316 33.8219 1.40496C35.0571 2.64024 34.9818 4.35759 33.6411 5.48743C32.8577 6.15026 31.9539 6.48168 30.9596 6.64739C30.8843 6.66245 30.824 6.67752 30.7336 6.7679C30.8542 6.8131 30.9897 6.84323 31.1103 6.90348C31.6526 7.20477 32.2702 7.41568 32.7071 7.82242C33.4904 8.53044 33.4452 9.61508 32.7071 10.3834C32.1798 10.9257 31.517 11.1969 30.7939 11.3324C30.7186 11.3475 30.6583 11.3626 30.583 11.3927C30.583 11.4228 30.583 11.4379 30.5227 11.5132Z" fill="#0078F0"/>
<path d="M29.6037 30.2383C29.2874 30.0425 28.9861 29.922 28.745 29.7111C28.3684 29.3947 28.278 28.9127 28.6095 28.5963C29.1668 28.0389 29.2874 27.3309 29.438 26.6229C29.664 25.6135 29.8447 24.5892 29.9653 23.9113C30.2364 25.0411 30.5678 26.4873 30.9143 27.9335C30.9595 28.0841 31.08 28.2348 31.2005 28.3553C31.7579 28.9578 31.6374 29.6056 30.8993 29.9672C30.7637 30.0425 30.613 30.0877 30.3569 30.1931C30.5528 30.2685 30.6582 30.2986 30.7486 30.3588C31.1102 30.5547 31.532 30.6903 31.8333 30.9614C32.4358 31.4887 32.4358 32.257 31.8333 32.7842C31.4717 33.1006 31.0047 33.2813 30.5678 33.5525C30.6733 33.5826 30.7938 33.6128 30.9143 33.673C31.4566 33.9291 32.0743 34.0948 32.5413 34.4564C33.5355 35.2397 33.5355 36.5654 32.5262 37.3337C32.014 37.7254 31.3813 37.9664 30.7787 38.2827C30.839 38.2978 30.9595 38.343 31.065 38.3731C32.1044 38.5539 33.0535 38.9305 33.8067 39.6837C35.0269 40.8889 35.0119 42.5309 33.7314 43.6758C32.4961 44.7755 31.0047 45.1069 29.3928 44.9714C28.3383 44.881 27.3742 44.5646 26.5306 43.9319C24.8283 42.6514 24.8584 40.5725 26.5908 39.3222C27.2687 38.8251 28.037 38.5388 28.8656 38.3882C28.9861 38.3581 29.1217 38.3279 29.2723 38.2978C28.6998 38.0266 28.1425 37.8459 27.6755 37.5446C26.395 36.701 26.395 35.1493 27.6755 34.3057C28.0822 34.0346 28.5944 33.899 29.0614 33.7031C29.1819 33.658 29.3326 33.6278 29.5736 33.5525C28.6396 33.2211 27.7056 32.9349 27.7508 31.8502C27.796 30.7505 28.745 30.5245 29.6037 30.2383Z" fill="#0078F0"/>
<path d="M210.422 21.1394C210.422 22.3295 210.422 23.5045 210.422 24.7097C210.256 24.7247 210.106 24.7398 209.955 24.7398C205.165 24.7398 200.389 24.7398 195.599 24.7548C195.207 24.7548 195.072 24.6494 195.087 24.2427C195.117 23.3237 195.102 22.4199 195.087 21.5009C195.087 21.1996 195.192 21.1093 195.493 21.1093C200.359 21.1243 205.24 21.1093 210.106 21.1093C210.196 21.1093 210.302 21.1243 210.422 21.1394Z" fill="#4A4F54"/>
<path d="M40.1493 43.0883C39.0647 43.028 37.724 42.6815 36.7749 41.4613C36.0819 40.5575 36.1271 39.4578 36.8653 38.584C37.6938 37.5898 38.8237 37.1981 40.0439 37.0926C41.3545 36.9872 42.5898 37.2583 43.6594 38.0718C45.1055 39.1715 45.1206 40.9793 43.6895 42.1091C42.8609 42.7569 41.7763 43.0883 40.1493 43.0883Z" fill="#0078F0"/>
<path d="M15.2474 5.26147C15.2323 3.96593 15.7445 3.31816 16.4526 2.7909C18.0644 1.60081 20.8212 1.60081 22.4482 2.76077C24.1053 3.95086 24.1204 5.83392 22.4633 7.02401C20.7158 8.27436 17.8385 8.18398 16.2266 6.84324C15.5637 6.30092 15.2474 5.66821 15.2474 5.26147Z" fill="#0078F0"/>
<path d="M49.0972 38.825C47.892 38.825 46.9128 38.5689 46.0843 37.891C44.8791 36.8968 44.864 35.4205 46.0541 34.4111C47.6058 33.0855 50.468 33.1307 51.9895 34.4865C53.1646 35.541 53.0139 37.1227 51.643 38.0718C50.8446 38.6292 49.9408 38.8552 49.0972 38.825Z" fill="#0078F0"/>
<path d="M11.1501 11.5432C9.91481 11.5583 8.92056 11.2871 8.07695 10.5791C6.88686 9.5698 6.93205 8.03323 8.16733 7.0691C9.7491 5.83382 12.3553 5.84888 13.9069 7.09923C15.097 8.06336 15.1422 9.53967 13.9822 10.549C13.2441 11.2118 12.2197 11.5432 11.1501 11.5432Z" fill="#0078F0"/>
<path d="M5.03392 12.643C6.4801 12.628 7.44423 12.8991 8.21251 13.6524C9.07119 14.496 9.05612 15.6258 8.19745 16.4694C6.90191 17.7499 4.19031 17.8252 2.81944 16.6201C1.67454 15.6107 1.76493 14.2097 3.04541 13.3209C3.69318 12.869 4.47653 12.643 5.03392 12.643Z" fill="#0078F0"/>
<path d="M54.4151 27.5418C55.6052 27.5418 56.5542 27.7979 57.3225 28.536C58.2264 29.4098 58.1661 30.7053 57.202 31.5037C55.8462 32.6335 53.4359 32.6787 52.0349 31.5941C50.8448 30.6752 50.8297 29.2892 52.0047 28.3552C52.758 27.7376 53.6317 27.5267 54.4151 27.5418Z" fill="#0078F0"/>
<path d="M3.07545 24.6193C2.14146 24.6193 1.29785 24.3934 0.604884 23.7305C-0.25379 22.902 -0.193532 21.7571 0.755528 21.0189C1.96068 20.0548 3.97932 20.0096 5.24473 20.8984C6.44989 21.7571 6.44989 23.1581 5.22967 24.0017C4.61203 24.4084 3.91906 24.6193 3.07545 24.6193Z" fill="#0078F0"/>
<path d="M56.9307 20.4012C57.699 20.371 58.407 20.5518 59.0397 20.9736C60.3051 21.8172 60.3051 23.2634 59.0548 24.1221C57.8797 24.9205 55.9816 24.9205 54.8066 24.1221C53.5713 23.2785 53.5562 21.8474 54.7915 21.0037C55.4393 20.5518 56.1624 20.371 56.9307 20.4012Z" fill="#0078F0"/>
<path d="M37.332 36.9118C36.5486 36.8817 35.7653 36.7009 35.1175 36.1436C34.1835 35.3451 34.2287 34.1852 35.1777 33.4169C36.3528 32.4829 38.4467 32.498 39.6067 33.447C40.5859 34.2454 40.5407 35.5109 39.5012 36.249C38.8685 36.7009 38.1454 36.8968 37.332 36.9118Z" fill="#0078F0"/>
<path d="M22.569 12.2514C21.8911 12.2665 21.2283 12.1158 20.6257 11.7091C19.3753 10.8956 19.3753 9.4645 20.6106 8.65102C21.7405 7.91286 23.5482 7.92793 24.663 8.68115C25.8531 9.49463 25.8681 10.8203 24.7082 11.6639C24.0754 12.1158 23.3674 12.2816 22.569 12.2514Z" fill="#0078F0"/>
<path d="M54.8522 13.0799C55.5904 13.0498 56.3135 13.2758 56.9311 13.803C57.7145 14.496 57.7295 15.4752 56.9612 16.1983C55.8917 17.1925 53.7525 17.2226 52.6528 16.2585C51.7489 15.4601 51.8393 14.3152 52.8637 13.6222C53.391 13.2456 54.0086 13.0799 54.8522 13.0799Z" fill="#0078F0"/>
<path d="M5.41041 31.9407C4.43123 31.9407 3.70813 31.7448 3.09049 31.2176C2.26195 30.5095 2.27701 29.44 3.10555 28.7319C4.145 27.8582 6.14857 27.813 7.21815 28.6415C8.22747 29.4249 8.19734 30.63 7.14283 31.3682C6.58544 31.7749 5.93767 31.9557 5.41041 31.9407Z" fill="#0078F0"/>
<path d="M43.373 30.1781C44.096 30.1932 44.8191 30.389 45.4067 30.9464C46.0996 31.6092 46.0695 32.5884 45.3615 33.2061C44.2919 34.1401 42.3636 34.1551 41.279 33.2512C40.4053 32.5131 40.4354 31.4586 41.3393 30.7807C41.9268 30.3438 42.5896 30.1781 43.373 30.1781Z" fill="#0078F0"/>
<path d="M16.754 11.0914C17.4168 11.0914 18.0495 11.2571 18.5918 11.6639C19.6162 12.4171 19.6011 13.562 18.5617 14.3002C17.5524 15.0233 15.8802 15.0082 14.8558 14.3002C13.7863 13.562 13.8013 12.3267 14.886 11.6036C15.4132 11.2571 16.0158 11.0914 16.754 11.0914Z" fill="#0078F0"/>
<path d="M11.1801 37.8759C10.3816 37.891 9.67361 37.6801 9.11623 37.1076C8.55885 36.5352 8.55885 35.797 9.10117 35.1945C10.0653 34.1249 12.2798 34.1249 13.2439 35.1794C13.7862 35.782 13.7862 36.5503 13.1987 37.1227C12.6262 37.6801 11.9333 37.891 11.1801 37.8759Z" fill="#0078F0"/>
<path d="M48.841 10.5942C48.1179 10.6093 47.4852 10.4436 46.958 9.99167C46.1897 9.3439 46.1897 8.42497 46.9278 7.76213C47.907 6.90346 49.8353 6.91852 50.7693 7.7772C51.5074 8.4551 51.5074 9.3439 50.7241 9.99167C50.1818 10.4436 49.534 10.6244 48.841 10.5942Z" fill="#0078F0"/>
<path d="M47.1841 29.4098C46.4309 29.3495 45.7379 29.1838 45.2107 28.6113C44.7136 28.069 44.7136 27.3459 45.1956 26.8036C46.0995 25.7943 48.2236 25.7792 49.1576 26.7735C49.715 27.361 49.6999 28.0992 49.1274 28.6716C48.5851 29.2139 47.9072 29.3495 47.1841 29.4098Z" fill="#0078F0"/>
<path d="M12.8221 18.9551C12.0839 18.9852 11.4512 18.7894 10.9089 18.3073C10.2762 17.7198 10.2611 16.9214 10.8788 16.3188C11.7977 15.4149 13.7109 15.3999 14.6449 16.2736C15.3529 16.9214 15.3379 17.765 14.5997 18.3826C14.1026 18.8044 13.4849 18.9852 12.8221 18.9551Z" fill="#0078F0"/>
<path d="M19.2998 41.9585C18.6972 41.9284 18.1248 41.7777 17.6427 41.3861C16.9498 40.8287 16.9498 39.9399 17.6277 39.3674C18.5315 38.6142 20.1284 38.5991 21.0322 39.3524C21.7402 39.9399 21.7252 40.8739 20.987 41.4313C20.4748 41.8079 19.9024 41.9434 19.2998 41.9585Z" fill="#0078F0"/>
<path d="M40.7365 3.06208C41.2638 3.03195 41.8061 3.19766 42.3032 3.54414C43.0414 4.0714 43.0866 4.94513 42.4388 5.56278C41.5651 6.40638 39.7423 6.39132 38.8836 5.53265C38.3413 4.99033 38.3262 4.25217 38.8685 3.70985C39.3657 3.24285 39.9833 3.06208 40.7365 3.06208Z" fill="#0078F0"/>
<path d="M48.8865 24.0167C48.2236 24.0317 47.6211 23.8811 47.139 23.4291C46.5665 22.8868 46.5967 22.0733 47.2143 21.5762C48.0579 20.8682 49.5644 20.8531 50.423 21.5461C51.1612 22.1336 51.1612 22.9772 50.408 23.5647C49.9711 23.9112 49.4439 24.0317 48.8865 24.0167Z" fill="#0078F0"/>
<path d="M33.6564 32.0762C32.873 31.5942 32.9785 30.6301 33.7166 30.1028C34.5151 29.5454 35.7955 29.5454 36.5939 30.0877C37.3773 30.6301 37.4225 31.5791 36.6241 32.0913C36.2023 32.3775 34.8615 32.8295 33.6564 32.0762Z" fill="#0078F0"/>
<path d="M24.8586 15.2944C24.2259 15.3094 23.6685 15.1739 23.2015 14.737C22.6743 14.2399 22.6743 13.5318 23.1865 13.0347C24 12.2363 25.7022 12.2514 26.5007 13.0648C26.9978 13.577 26.9978 14.2248 26.4856 14.7219C26.0337 15.1588 25.4612 15.3245 24.8586 15.2944Z" fill="#0078F0"/>
<path d="M47.4704 18.6086C46.7473 18.6086 46.2502 18.4579 45.8284 18.0813C45.3012 17.5992 45.3162 16.9213 45.8435 16.4393C46.6118 15.7463 48.1032 15.7463 48.8564 16.4393C49.3384 16.8761 49.3686 17.554 48.9016 18.021C48.4647 18.4579 47.9073 18.6086 47.4704 18.6086Z" fill="#0078F0"/>
<path d="M37.9194 30.0123C37.3168 29.6056 37.3469 28.7921 37.9344 28.3401C38.6726 27.7677 39.923 27.7526 40.6611 28.3251C41.2788 28.7921 41.2938 29.6357 40.631 30.0424C40.2393 30.2835 39.0342 30.645 37.9194 30.0123Z" fill="#0078F0"/>
<path d="M20.6556 14.5563C21.2581 14.5563 21.7553 14.6768 22.162 15.0534C22.6441 15.5053 22.6441 16.123 22.1771 16.59C21.454 17.298 19.9927 17.3131 19.2546 16.6051C18.7574 16.1381 18.7725 15.4903 19.2696 15.0384C19.6764 14.6617 20.1735 14.5412 20.6556 14.5563Z" fill="#0078F0"/>
<path d="M44.4576 12.176C44.9999 12.5225 45.015 13.2305 44.548 13.6824C43.855 14.3453 42.4691 14.3302 41.7912 13.6674C41.3543 13.2305 41.3694 12.5375 41.8966 12.1911C42.9662 11.5282 44.0961 11.935 44.4576 12.176Z" fill="#0078F0"/>
<path d="M17.9442 19.9945C17.4471 20.0095 16.9952 19.8739 16.6336 19.5124C16.2269 19.1207 16.2269 18.6085 16.6186 18.2018C17.2663 17.5239 18.6673 17.5239 19.3151 18.2018C19.7068 18.6085 19.7068 19.1057 19.3 19.5124C18.9234 19.8739 18.4564 20.0095 17.9442 19.9945Z" fill="#0078F0"/>
<path d="M42.0019 25.026C42.5291 25.011 42.9961 25.1164 43.3727 25.493C43.7644 25.8847 43.7644 26.412 43.3727 26.8037C42.74 27.4514 41.3691 27.4665 40.7063 26.8187C40.2845 26.3969 40.2694 25.8998 40.6912 25.478C41.0679 25.1315 41.5198 24.9959 42.0019 25.026Z" fill="#0078F0"/>
<path d="M23.503 34.2002C24.2412 34.622 24.2412 35.4355 23.488 35.8423C22.795 36.2189 22.087 36.2038 21.4241 35.7519C20.8366 35.3602 20.8366 34.622 21.4392 34.2454C21.7706 34.0797 22.6594 33.7784 23.503 34.2002Z" fill="#0078F0"/>
<path d="M36.2474 10.5943C35.7805 10.2328 35.8407 9.67538 36.2926 9.2837C36.8802 8.78657 37.9949 8.77151 38.6126 9.25357C39.1097 9.64525 39.17 10.2478 38.6728 10.6094C38.3414 10.8655 37.3321 11.2571 36.2474 10.5943Z" fill="#0078F0"/>
<path d="M42.5895 23.4594C42.0623 23.2937 41.7007 22.887 41.7158 22.4953C41.7309 22.1187 42.1527 21.6969 42.6498 21.5613C43.1469 21.4257 43.629 21.4558 44.0809 21.6969C44.4123 21.8776 44.6835 22.1337 44.6684 22.5405C44.6534 22.9322 44.3822 23.2033 44.0357 23.354C43.7645 23.4745 43.3729 23.6402 42.5895 23.4594Z" fill="#0078F0"/>
<path d="M15.7144 23.1279C15.2022 22.7663 15.2172 22.209 15.6993 21.8022C16.2717 21.3202 17.3564 21.3202 17.9288 21.8022C18.3958 22.1939 18.3958 22.8417 17.8686 23.1731C16.9496 23.7305 16.0157 23.3539 15.7144 23.1279Z" fill="#0078F0"/>
<path d="M41.1132 19.3769C40.6914 19.0605 40.7366 18.5634 41.1433 18.232C41.6555 17.8102 42.6046 17.8102 43.1167 18.232C43.5235 18.5634 43.5837 19.0605 43.1619 19.3769C42.8908 19.5878 41.9417 19.9494 41.1132 19.3769Z" fill="#0078F0"/>
<path d="M20.7459 30.0123C20.1132 30.0123 19.601 29.6357 19.616 29.1687C19.616 28.7318 20.1132 28.3703 20.7308 28.3552C20.7459 28.3552 20.7609 28.3552 20.776 28.3552C21.4087 28.3552 21.9209 28.7168 21.9209 29.1687C21.9209 29.6508 21.4087 30.0274 20.7459 30.0123Z" fill="#0078F0"/>
<path d="M39.2451 15.0081C39.923 15.0081 40.4352 15.3847 40.4051 15.8667C40.375 16.3337 39.7272 16.7254 39.1246 16.6501C38.507 16.5748 38.04 16.2132 38.055 15.8065C38.0701 15.3545 38.5974 15.0081 39.2451 15.0081Z" fill="#0078F0"/>
<path d="M24.783 30.5245C25.3554 30.5245 25.8526 30.9011 25.8224 31.2928C25.7923 31.6996 25.1445 32.0762 24.6323 31.9858C24.075 31.8954 23.7134 31.579 23.7285 31.2024C23.7435 30.8409 24.2407 30.5245 24.783 30.5245Z" fill="#0078F0"/>
<path d="M35.2377 13.0046C35.8102 13.0046 36.3224 13.3813 36.2772 13.7729C36.2471 14.1646 35.6144 14.5412 35.1022 14.481C34.5297 14.4056 34.138 14.0592 34.1832 13.6675C34.2284 13.3059 34.7105 13.0046 35.2377 13.0046Z" fill="#0078F0"/>
<path d="M17.9138 27.0899C17.2208 27.0748 16.6635 26.6681 16.6785 26.171C16.6785 25.6889 17.2208 25.2972 17.8987 25.2671C17.9138 25.2671 17.9289 25.2671 17.9439 25.2671C18.6369 25.2671 19.1943 25.6588 19.2093 26.171C19.1943 26.6982 18.6218 27.105 17.9138 27.0899Z" fill="#0078F0"/>
<path d="M10.9992 23.9714C10.3364 23.9865 9.76396 23.8208 9.29696 23.3839C8.72451 22.8567 8.72451 22.1487 9.2819 21.6063C10.0954 20.8079 11.8127 20.7778 12.6563 21.5611C13.289 22.1486 13.274 22.8868 12.6111 23.4442C12.1441 23.8359 11.5868 24.0016 10.9992 23.9714Z" fill="#0078F0"/>
<path d="M12.4758 29.0482C11.8883 29.0633 11.3911 28.9126 10.9693 28.536C10.4722 28.069 10.4571 27.4363 10.9543 26.9693C11.6774 26.2613 13.1838 26.2462 13.937 26.9241C14.4944 27.4363 14.4793 28.0992 13.9069 28.5812C13.4851 28.9277 12.988 29.0633 12.4758 29.0482Z" fill="#0078F0"/>
<path d="M16.7089 33.206C16.1967 33.2211 15.7448 33.0855 15.3682 32.7541C14.9163 32.3473 14.9163 31.7899 15.3531 31.3681C16.0009 30.7354 17.3266 30.7204 17.9894 31.338C18.4865 31.7899 18.4715 32.3774 17.9593 32.8143C17.5977 33.1005 17.1609 33.2361 16.7089 33.206Z" fill="#0078F0"/>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

+212
View File
@@ -0,0 +1,212 @@
// 创建一个自执行的函数,用于封装模块定义和执行逻辑
!function (n) {
// 定义模块存储对象和模块导出相关函数
var e = {};
function t(i) {
// 模块缓存逻辑,避免重复执行
if (e[i]) return e[i].exports;
var o = e[i] = { i: i, l: !1, exports: {} };
// 执行模块定义函数并缓存结果
return n[i].call(o.exports, o, o.exports, t),
o.l = !0,
o.exports
}
// 初始化模块系统,定义模块数组、缓存对象、导出函数等
t.m = n,
t.c = e,
t.d = function (n, e, i) {
t.o(n, e) || Object.defineProperty(n, e, { enumerable: !0, get: i })
},
t.r = function (n) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(n, Symbol.toStringTag, { value: "Module" }),
Object.defineProperty(n, "__esModule", { value: !0 })
},
t.t = function (n, e) {
if (1 & e && (n = t(n)), 8 & e) return n;
if (4 & e && "object" == typeof n && n && n.__esModule) return n;
var i = Object.create(null);
if (t.r(i), Object.defineProperty(i, "default", { enumerable: !0, value: n }),
2 & e && "string" != typeof n) for (var o in n)
t.d(i, o, function (e) { return n[e] }.bind(null, o));
return i
},
t.n = function (n) {
var e = n && n.__esModule ? function () { return n.default } : function () { return n };
return t.d(e, "a", e), e
},
t.o = function (n, e) { return Object.prototype.hasOwnProperty.call(n, e) },
t.p = "",
// 执行入口模块
t(t.s = 0)
}([
// 定义模块数组,每个模块是一个函数
function (n, e, t) {
// 执行依赖模块并导出结果
t(1),
n.exports = t(3)
},
function (n, e, t) {
// 根据环境获取jQuery对象
(function () {
var e = "undefined" != typeof window ? window.jQuery : t(2);
// 定义并导出ThemeNav对象
n.exports.ThemeNav = {
navBar: null,
win: null,
winScroll: !1,
winResize: !1,
linkScroll: !1,
winPosition: 0,
winHeight: null,
docHeight: null,
isRunning: !1,
// 启用导航栏功能
enable: function (n) {
var t = this;
void 0 === n && (n = !0),
t.isRunning || (t.isRunning = !0,
e((function (e) {
t.init(e),
t.reset(),
t.win.on("hashchange", t.reset),
n && t.win.on("scroll", (function () {
t.linkScroll || t.winScroll || (t.winScroll = !0,
requestAnimationFrame((function () {
t.onScroll()
})))
})),
t.win.on("resize", (function () {
t.winResize || (t.winResize = !0,
requestAnimationFrame((function () {
t.onResize()
})))
})),
t.onResize()
})))
},
// 启用粘性导航栏
enableSticky: function () {
this.enable(!0)
},
// 初始化导航栏
init: function (n) {
n(document);
var e = this;
this.navBar = n("div.wy-side-scroll:first"),
this.win = n(window),
n(document).on("click", "[data-toggle='wy-nav-top']", (function () {
n("[data-toggle='wy-nav-shift']").toggleClass("shift"),
n("[data-toggle='rst-versions']").toggleClass("shift")
})).on("click", ".wy-menu-vertical .current ul li a", (function () {
var t = n(this);
n("[data-toggle='wy-nav-shift']").removeClass("shift"),
n("[data-toggle='rst-versions']").toggleClass("shift"),
e.toggleCurrent(t),
e.hashChange()
})).on("click", "[data-toggle='rst-current-version']", (function () {
n("[data-toggle='rst-versions']").toggleClass("shift-up")
})),
n("table.docutils:not(.field-list,.footnote,.citation)").wrap("<div class='wy-table-responsive'></div>"),
n("table.docutils.footnote").wrap("<div class='wy-table-responsive footnote'></div>"),
n("table.docutils.citation").wrap("<div class='wy-table-responsive citation'></div>"),
n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function () {
var t = n(this);
expand = n('<button class="toctree-expand" title="Open/close menu"></button>'),
expand.on("click", (function (n) {
return e.toggleCurrent(t),
n.stopPropagation(),
!1
})),
t.prepend(expand)
}))
},
// 重置导航栏状态
reset: function () {
var n = encodeURI(window.location.hash) || "#";
try {
var e = $(".wy-menu-vertical"),
t = e.find('[href="' + n + '"]');
if (0 === t.length) {
var i = $('.document [id="' + n.substring(1) + '"]').closest("div.section");
0 === (t = e.find('[href="#' + i.attr("id") + '"]')).length && (t = e.find('[href="#"]'))
}
if (t.length > 0) {
$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded", "false"),
t.addClass("current").attr("aria-expanded", "true"),
t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded", "true");
for (let n = 1; n <= 10; n++)
t.closest("li.toctree-l" + n).addClass("current").attr("aria-expanded", "true");
t[0].scrollIntoView()
}
} catch (n) {
console.log("Error expanding nav for anchor", n)
}
},
// 滚动事件处理
onScroll: function () {
this.winScroll = !1;
var n = this.win.scrollTop(),
e = n + this.winHeight,
t = this.navBar.scrollTop() + (n - this.winPosition);
n < 0 || e > this.docHeight || (this.navBar.scrollTop(t),
this.winPosition = n)
},
// 窗口大小变化事件处理
onResize: function () {
this.winResize = !1,
this.winHeight = this.win.height(),
this.docHeight = $(document).height()
},
// hash变化事件处理
hashChange: function () {
this.linkScroll = !0,
this.win.one("hashchange", (function () {
this.linkScroll = !1
}))
},
// 切换当前导航项
toggleCurrent: function (n) {
var e = n.closest("li");
// 20201030 a
e.siblings("li.current").removeClass("current").attr("aria-expanded", "false"),
e.siblings().find("li.current").removeClass("current").attr("aria-expanded", "false");
var t = e.find("> ul li");
t.length && (t.removeClass("current").attr("aria-expanded", "false"),
e.toggleClass("current").attr("aria-expanded", (function (n, e) {
return "true" == e ? "false" : "true"
})))
}
},
"undefined" != typeof window && (window.SphinxRtdTheme = {
Navigation: n.exports.ThemeNav,
StickyNav: n.exports.ThemeNav
}),
// 实现跨浏览器的requestAnimationFrame和cancelAnimationFrame方法
function () {
for (var n = 0, e = ["ms", "moz", "webkit", "o"], t = 0; t < e.length && !window.requestAnimationFrame; ++t)
window.requestAnimationFrame = window[e[t] + "RequestAnimationFrame"],
window.cancelAnimationFrame = window[e[t] + "CancelAnimationFrame"] || window[e[t] + "CancelRequestAnimationFrame"];
window.requestAnimationFrame || (window.requestAnimationFrame = function (e, t) {
var i = (new Date).getTime(),
o = Math.max(0, 16 - (i - n)),
r = window.setTimeout((function () {
e(i + o)
}), o);
return n = i + o,
r
}),
window.cancelAnimationFrame || (window.cancelAnimationFrame = function (n) {
clearTimeout(n)
})
}()
}).call(window)
},
function (n, e) {
// 导出jQuery对象
n.exports = jQuery
},
function (n, e, t) {
// 未定义的模块体
}
]);
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+292
View File
@@ -0,0 +1,292 @@
{# TEMPLATE VAR SETTINGS #}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
{%- set lang_attr = 'en' if language == None else (language | replace('_', '-')) %}
{%- set sphinx_writer = 'writer-html5' if html5_doctype else 'writer-html4' -%}
{# Build sphinx_version_info tuple from sphinx_version string in pure Jinja #}
{%- set (_ver_major, _ver_minor) = (sphinx_version.split('.') | list)[:2] | map('int') -%}
{%- set sphinx_version_info = (_ver_major, _ver_minor, -1) -%}
<!DOCTYPE html>
<html class="{{ sphinx_writer }}" lang="{{ lang_attr }}" {% if sphinx_version_info>= (7, 2) %} data-content_root="{{
content_root }}"{% endif %}>
<head>
<meta charset="utf-8" />
{{- metatags }}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{%- block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{%- endblock -%}
{#- CSS #}
{%- if sphinx_version_info
< (4, 0) -%} <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- endif %}
{%- for css_file in css_files %}
{%- if css_file|attr("filename") %}
{{ css_tag(css_file) }}
{%- else %}
<link rel="stylesheet" href="{{ pathto(css_file, 1)|escape }}" type="text/css" />
{%- endif %}
{%- endfor %}
{# "extra_css_files" is a theme option and it's always a string #}
{%- for css_file in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(css_file, 1)|escape }}" type="text/css" />
{%- endfor -%}
{#- FAVICON
favicon_url is the only context var necessary since Sphinx 4.
In Sphinx
<4, we use favicon but need to prepend path info. #} {%- set _favicon_url=favicon_url | default(pathto('_static/' +
(favicon or "" ), 1)) %} {%- if favicon_url or favicon %} <link rel="shortcut icon" href="{{ _favicon_url }}" />
{%- endif %}
{#- CANONICAL URL (deprecated) #}
{%- if theme_canonical_url and not pageurl %}
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html" />
{%- endif -%}
{#- CANONICAL URL #}
{%- if pageurl %}
<link rel="canonical" href="{{ pageurl|e }}" />
{%- endif -%}
{#- JAVASCRIPTS #}
{%- block scripts %}
<!--[if lt IE 9]>
<script src="{{ pathto('_static/js/html5shiv.min.js', 1) }}"></script>
<![endif]-->
{%- if not embedded %}
{# XXX Sphinx 1.8.0 made this an external js-file, quick fix until we refactor the template to inherert more blocks
directly from sphinx #}
{%- if sphinx_version_info >= (1, 8) -%}
{%- if sphinx_version_info < (4, 0) -%} <script id="documentation_options" data-url_root="{{ url_root }}"
src="{{ pathto('_static/documentation_options.js', 1) }}">
</script>
{%- endif -%}
{%- for scriptfile in script_files %}
{{ js_tag(scriptfile) }}
{%- endfor %}
{%- else %}
<script>
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
LANGUAGE: '{{ language }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source| lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
</script>
{%- for scriptfile in script_files %}
<script src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- endif %}
<script src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{#- OPENSEARCH #}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}" />
{%- endif %}
{%- endif %}
{%- endblock %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body class="wy-body-for-nav">
{%- block extrabody %} {% endblock %}
<div class="wy-grid-for-nav">
{#- SIDE NAV, TOGGLES ON MOBILE #}
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" {% if theme_style_nav_header_background %}
style="background: {{theme_style_nav_header_background}}" {% endif %}>
{%- block sidebartitle %}
{# the logo helper function was removed in Sphinx 6 and deprecated since Sphinx 4 #}
{# the master_doc variable was renamed to root_doc in Sphinx 4 (master_doc still exists in later
Sphinx versions) #}
{%- set _logo_url = logo_url|default(pathto('_static/' + (logo or ""), 1)) %}
{%- set _root_doc = root_doc|default(master_doc) %}
<a href="{{ pathto(_root_doc) }}" {% if not theme_logo_only %} class="icon icon-home" {% endif %}>
{% if not theme_logo_only %}{{ project }}{% endif %}
{%- if logo or logo_url %}
<img src="{{ _logo_url }}" class="logo" alt="{{ _('Logo') }}" />
{%- endif %}
</a>
{%- if theme_display_version %}
{%- set nav_version = version %}
{%- if READTHEDOCS and current_version %}
{%- set nav_version = current_version %}
{%- endif %}
{%- if nav_version %}
<div class="version">
{{ nav_version }}
</div>
{%- endif %}
{%- endif %}
{%- include "searchbox.html" %}
{%- endblock %}
</div>
{%- block navigation %}
{#- Translators: This is an ARIA section label for the main navigation menu -#}
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation"
aria-label="{{ _('Navigation menu') }}">
{%- block menu %}
{%- set toctree = toctree(maxdepth=theme_navigation_depth|int,
collapse=theme_collapse_navigation|tobool,
includehidden=theme_includehidden|tobool,
titles_only=theme_titles_only|tobool) %}
{%- if toctree %}
{{ toctree }}
{%- else %}
<!-- Local TOC -->
<div class="local-toc">{{ toc }}</div>
{%- endif %}
{%- endblock %}
</div>
{%- endblock %}
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
{#- MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
{#- Translators: This is an ARIA section label for the navigation menu that is visible when viewing the page
on mobile devices -#}
<nav class="wy-nav-top" aria-label="{{ _('Mobile navigation menu') }}" {% if
theme_style_nav_header_background %} style="background: {{theme_style_nav_header_background}}" {% endif
%}>
{%- block mobile_nav %}
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="{{ pathto(master_doc) }}">{{ project }}</a>
{%- endblock %}
</nav>
<div class="wy-nav-content">
{%- block content %}
{%- if theme_style_external_links|tobool %}
<div class="rst-content style-external-links">
{%- else %}
<div class="rst-content">
{%- endif %}
{% include "breadcrumbs.html" %}
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
{%- block document %}
<div itemprop="articleBody">
{% block body %}{% endblock %}
</div>
{%- if self.comments()|trim %}
<div class="articleComments">
{%- block comments %}{% endblock %}
</div>
{%- endif%}
</div>
{%- endblock %}
{% include "footer.html" %}
</div>
{%- endblock %}
</div>
</section>
</div>
{% include "versions.html" -%}
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable({{ 'true' if theme_sticky_navigation | tobool else 'false' }});
});
</script>
{#- Do not conflict with RTD insertion of analytics script #}
{%- if not READTHEDOCS %}
{%- if theme_analytics_id %}
<!-- Theme Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ theme_analytics_id }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', '{{ theme_analytics_id }}', {
'anonymize_ip': {{ 'true' if theme_analytics_anonymize_ip | tobool else 'false' }},
});
</script>
{%- endif %}
{%- endif %}
{%- block footer %} {% endblock %}
{% extends "!layout.html" %}
{% block body %}
{{ super() }}
<!-- 在这里添加你的自定义内容 -->
{% if theme_logo %}
<div class="logoheader">
<a href="{{ pathto(master_doc) }}">
<img src="{{ pathto('_static/' + theme_logo, 1) }}" alt="Logo" />
</a>
</div>
{% endif %}
<div class="document-wrapper">
<div class="document">
<div class="body">
{% if pagename == 'index' %}
<h1>{{ title }}</h1>
{% else %}
<h2>{{ title }}</h2>
{% endif %}
{{ super() }}
</div>
</div>
<div class="sidebar">
{{ sidebar }}
</div>
</div>
{% endblock %}
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 736 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Some files were not shown because too many files have changed in this diff Show More