diff --git a/install/bcr_bot/share/ament_index/resource_index/parent_prefix_path/bcr_bot b/install/bcr_bot/share/ament_index/resource_index/parent_prefix_path/bcr_bot
index 6350bc1..d9635cf 100644
--- a/install/bcr_bot/share/ament_index/resource_index/parent_prefix_path/bcr_bot
+++ b/install/bcr_bot/share/ament_index/resource_index/parent_prefix_path/bcr_bot
@@ -1 +1 @@
-/opt/ros/humble
\ No newline at end of file
+/workspace/install/ros_viz_adapter:/workspace/install/bcr_bot:/opt/ros/humble
\ No newline at end of file
diff --git a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gazebo_spawn.launch.py b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gazebo_spawn.launch.py
index 9cc11f5..eb61507 100644
--- a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gazebo_spawn.launch.py
+++ b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gazebo_spawn.launch.py
@@ -25,7 +25,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True)
- stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False)
+ stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source", default="world")
robot_namespace = LaunchConfiguration("robot_namespace", default='bcr_bot')
diff --git a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gz_spawn.launch.py b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gz_spawn.launch.py
index 6faec90..3be3750 100644
--- a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gz_spawn.launch.py
+++ b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_gz_spawn.launch.py
@@ -23,7 +23,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True)
- stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False)
+ stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source")
@@ -126,4 +126,4 @@ def generate_launch_description():
DeclareLaunchArgument("odometry_source", default_value="world"),
robot_state_publisher,
gz_spawn_entity, transform_publisher, gz_ros2_bridge
- ])
\ No newline at end of file
+ ])
diff --git a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_ign_spawn.launch.py b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_ign_spawn.launch.py
index e7671d3..ba7ee63 100644
--- a/install/bcr_bot/share/bcr_bot/launch/bcr_bot_ign_spawn.launch.py
+++ b/install/bcr_bot/share/bcr_bot/launch/bcr_bot_ign_spawn.launch.py
@@ -23,7 +23,7 @@ def generate_launch_description():
position_y = LaunchConfiguration("position_y")
orientation_yaw = LaunchConfiguration("orientation_yaw")
camera_enabled = LaunchConfiguration("camera_enabled", default=True)
- stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=False)
+ stereo_camera_enabled = LaunchConfiguration("stereo_camera_enabled", default=True)
two_d_lidar_enabled = LaunchConfiguration("two_d_lidar_enabled", default=True)
odometry_source = LaunchConfiguration("odometry_source")
diff --git a/install/bcr_bot/share/bcr_bot/urdf/bcr_bot.xacro b/install/bcr_bot/share/bcr_bot/urdf/bcr_bot.xacro
index 7cac6a9..0575ce4 100644
--- a/install/bcr_bot/share/bcr_bot/urdf/bcr_bot.xacro
+++ b/install/bcr_bot/share/bcr_bot/urdf/bcr_bot.xacro
@@ -38,7 +38,7 @@
-
+
diff --git a/install/ros_viz_adapter/lib/ros_viz_adapter/adapter b/install/ros_viz_adapter/lib/ros_viz_adapter/adapter
new file mode 100755
index 0000000..42c1888
Binary files /dev/null and b/install/ros_viz_adapter/lib/ros_viz_adapter/adapter differ
diff --git a/install/ros_viz_adapter/share/ament_index/resource_index/package_run_dependencies/ros_viz_adapter b/install/ros_viz_adapter/share/ament_index/resource_index/package_run_dependencies/ros_viz_adapter
new file mode 100644
index 0000000..3ac77eb
--- /dev/null
+++ b/install/ros_viz_adapter/share/ament_index/resource_index/package_run_dependencies/ros_viz_adapter
@@ -0,0 +1 @@
+rclcpp;sensor_msgs;image_transport;pluginlib;compressed_image_transport;compressed_depth_image_transport
\ No newline at end of file
diff --git a/install/ros_viz_adapter/share/ament_index/resource_index/packages/ros_viz_adapter b/install/ros_viz_adapter/share/ament_index/resource_index/packages/ros_viz_adapter
new file mode 100644
index 0000000..e69de29
diff --git a/install/ros_viz_adapter/share/ament_index/resource_index/parent_prefix_path/ros_viz_adapter b/install/ros_viz_adapter/share/ament_index/resource_index/parent_prefix_path/ros_viz_adapter
new file mode 100644
index 0000000..d9635cf
--- /dev/null
+++ b/install/ros_viz_adapter/share/ament_index/resource_index/parent_prefix_path/ros_viz_adapter
@@ -0,0 +1 @@
+/workspace/install/ros_viz_adapter:/workspace/install/bcr_bot:/opt/ros/humble
\ No newline at end of file
diff --git a/install/ros_viz_adapter/share/colcon-core/packages/ros_viz_adapter b/install/ros_viz_adapter/share/colcon-core/packages/ros_viz_adapter
new file mode 100644
index 0000000..c35dc2b
--- /dev/null
+++ b/install/ros_viz_adapter/share/colcon-core/packages/ros_viz_adapter
@@ -0,0 +1 @@
+compressed_depth_image_transport:compressed_image_transport:image_transport:pluginlib:rclcpp:sensor_msgs
\ No newline at end of file
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/README.md b/install/ros_viz_adapter/share/ros_viz_adapter/README.md
new file mode 100644
index 0000000..bcf981e
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/README.md
@@ -0,0 +1,93 @@
+# ros_viz_adapter
+
+通用 ROS 2 可视化发布适配器,不需要用户修改原始话题名称,也不需要
+YAML 配置文件。节点自动发现 `sensor_msgs/msg/Image` 和
+`sensor_msgs/msg/PointCloud2`,并把结果发布到 `/viz` 命名空间。
+
+## 输出
+
+- RGB:直接加载 `image_transport/compressed_pub`,插件发布
+ `/viz//rgb/compressed`,不创建 raw base topic。
+- 深度:直接加载 `image_transport/compressedDepth_pub`,插件发布
+ `/viz//depth/compressedDepth`,不创建 raw base topic。
+- 点云:`/viz//points`,消息仍为 `sensor_msgs/msg/PointCloud2`,但只保留
+ `x/y/z`,去除 NaN,执行体素降采样、最大点数限制和限频。
+
+图像依据 `encoding` 分类:`rgb8/bgr8/rgba8/bgra8/mono8` 为 RGB,
+`16UC1/32FC1/mono16/32SC1` 为深度。RGB、深度、点云各使用一个独立处理线程;
+不存在对应数据类型时,不创建该线程。
+
+## 运行
+
+```bash
+colcon build --packages-select ros_viz_adapter --symlink-install
+ros2 launch ros_viz_adapter adapter.launch.py
+```
+
+参数:
+
+```text
+output_namespace 默认 /viz
+input_fps_limit 默认 30,回调入口丢弃超频帧
+output_fps 默认 10,处理线程输出上限
+jpeg_quality 默认 80,范围 1-100
+voxel_size_m 默认 0.05
+max_points 默认 100000
+```
+
+QoS 为 `BEST_EFFORT + KEEP_LAST + depth=1`。限频降低的是适配器处理、网络和
+平台负载;如果还要降低源容器 CPU,应同时调整相机/上游发布频率。
+
+## 在其他项目中接入
+
+### 同一个 colcon 工作空间
+
+把本包目录放到项目工作空间的 `src/` 下,然后正常构建:
+
+```bash
+cd
+colcon build --symlink-install
+source install/setup.bash
+ros2 launch ros_viz_adapter adapter.launch.py
+```
+
+不需要修改原始 RGB、深度或点云节点。适配器会在同一个 ROS domain 中发现传感器话题,
+并发布 `/viz/...`。
+
+### 在项目 launch 中启动
+
+也可以在项目自己的 launch 文件中包含适配器:
+
+```python
+from launch.actions import IncludeLaunchDescription
+from launch.launch_description_sources import PythonLaunchDescriptionSource
+from launch_ros.substitutions import FindPackageShare
+
+viz_adapter = IncludeLaunchDescription(
+ PythonLaunchDescriptionSource([
+ FindPackageShare('ros_viz_adapter'), '/launch/adapter.launch.py'
+ ])
+)
+```
+
+将 `viz_adapter` 放入项目的 `LaunchDescription` 即可。也可以直接运行:
+
+```bash
+ros2 run ros_viz_adapter adapter
+```
+
+### 独立 ROS 容器或 sidecar
+
+适配器容器与用户容器必须使用相同的 `ROS_DOMAIN_ID`、`RMW_IMPLEMENTATION` 和可互相发现的
+ROS 2 网络。适配器容器只需安装本包、`compressed_image_transport` 和
+`compressed_depth_image_transport`,不需要复制用户项目代码。代码只加载上述两个
+指定插件,不遍历或加载 Theora 插件。
+
+### 多容器隔离
+
+为避免不同容器输出重名,可以指定不同 namespace:
+
+```bash
+ros2 launch ros_viz_adapter adapter.launch.py \
+ output_namespace:=/viz/robot_01
+```
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig-version.cmake b/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig-version.cmake
new file mode 100644
index 0000000..0b5f063
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig-version.cmake
@@ -0,0 +1,14 @@
+# generated from ament/cmake/core/templates/nameConfig-version.cmake.in
+set(PACKAGE_VERSION "0.2.0")
+
+set(PACKAGE_VERSION_EXACT False)
+set(PACKAGE_VERSION_COMPATIBLE False)
+
+if("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}")
+ set(PACKAGE_VERSION_EXACT True)
+ set(PACKAGE_VERSION_COMPATIBLE True)
+endif()
+
+if("${PACKAGE_FIND_VERSION}" VERSION_LESS "${PACKAGE_VERSION}")
+ set(PACKAGE_VERSION_COMPATIBLE True)
+endif()
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig.cmake b/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig.cmake
new file mode 100644
index 0000000..a96363b
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/cmake/ros_viz_adapterConfig.cmake
@@ -0,0 +1,42 @@
+# generated from ament/cmake/core/templates/nameConfig.cmake.in
+
+# prevent multiple inclusion
+if(_ros_viz_adapter_CONFIG_INCLUDED)
+ # ensure to keep the found flag the same
+ if(NOT DEFINED ros_viz_adapter_FOUND)
+ # explicitly set it to FALSE, otherwise CMake will set it to TRUE
+ set(ros_viz_adapter_FOUND FALSE)
+ elseif(NOT ros_viz_adapter_FOUND)
+ # use separate condition to avoid uninitialized variable warning
+ set(ros_viz_adapter_FOUND FALSE)
+ endif()
+ return()
+endif()
+set(_ros_viz_adapter_CONFIG_INCLUDED TRUE)
+
+# output package information
+if(NOT ros_viz_adapter_FIND_QUIETLY)
+ message(STATUS "Found ros_viz_adapter: 0.2.0 (${ros_viz_adapter_DIR})")
+endif()
+
+# warn when using a deprecated package
+if(NOT "" STREQUAL "")
+ set(_msg "Package 'ros_viz_adapter' is deprecated")
+ # append custom deprecation text if available
+ if(NOT "" STREQUAL "TRUE")
+ set(_msg "${_msg} ()")
+ endif()
+ # optionally quiet the deprecation message
+ if(NOT ${ros_viz_adapter_DEPRECATED_QUIET})
+ message(DEPRECATION "${_msg}")
+ endif()
+endif()
+
+# flag package as ament-based to distinguish it after being find_package()-ed
+set(ros_viz_adapter_FOUND_AMENT_PACKAGE TRUE)
+
+# include all config extra files
+set(_extras "")
+foreach(_extra ${_extras})
+ include("${ros_viz_adapter_DIR}/${_extra}")
+endforeach()
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.dsv b/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.dsv
new file mode 100644
index 0000000..79d4c95
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;AMENT_PREFIX_PATH;
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.sh b/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.sh
new file mode 100644
index 0000000..02e441b
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/environment/ament_prefix_path.sh
@@ -0,0 +1,4 @@
+# copied from
+# ament_cmake_core/cmake/environment_hooks/environment/ament_prefix_path.sh
+
+ament_prepend_unique_value AMENT_PREFIX_PATH "$AMENT_CURRENT_PREFIX"
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.dsv b/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.dsv
new file mode 100644
index 0000000..b94426a
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate-if-exists;PATH;bin
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.sh b/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.sh
new file mode 100644
index 0000000..e59b749
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/environment/path.sh
@@ -0,0 +1,5 @@
+# copied from ament_cmake_core/cmake/environment_hooks/environment/path.sh
+
+if [ -d "$AMENT_CURRENT_PREFIX/bin" ]; then
+ ament_prepend_unique_value PATH "$AMENT_CURRENT_PREFIX/bin"
+fi
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.dsv b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.dsv
new file mode 100644
index 0000000..e119f32
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;CMAKE_PREFIX_PATH;
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.ps1 b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.ps1
new file mode 100644
index 0000000..d03facc
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.ps1
@@ -0,0 +1,3 @@
+# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
+
+colcon_prepend_unique_value CMAKE_PREFIX_PATH "$env:COLCON_CURRENT_PREFIX"
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.sh b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.sh
new file mode 100644
index 0000000..a948e68
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/hook/cmake_prefix_path.sh
@@ -0,0 +1,3 @@
+# generated from colcon_core/shell/template/hook_prepend_value.sh.em
+
+_colcon_prepend_unique_value CMAKE_PREFIX_PATH "$COLCON_CURRENT_PREFIX"
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/launch/adapter.launch.py b/install/ros_viz_adapter/share/ros_viz_adapter/launch/adapter.launch.py
new file mode 100644
index 0000000..f822e51
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/launch/adapter.launch.py
@@ -0,0 +1,17 @@
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ return LaunchDescription([
+ DeclareLaunchArgument('output_namespace', default_value='/viz'),
+ Node(
+ package='ros_viz_adapter', executable='adapter',
+ name='ros_viz_adapter', output='screen',
+ parameters=[{
+ 'output_namespace': LaunchConfiguration('output_namespace'),
+ }],
+ ),
+ ])
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.bash b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.bash
new file mode 100644
index 0000000..49782f2
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.bash
@@ -0,0 +1,46 @@
+# generated from ament_package/template/package_level/local_setup.bash.in
+
+# source local_setup.sh from same directory as this file
+_this_path=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" && pwd)
+# provide AMENT_CURRENT_PREFIX to shell script
+AMENT_CURRENT_PREFIX=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." && pwd)
+# store AMENT_CURRENT_PREFIX to restore it before each environment hook
+_package_local_setup_AMENT_CURRENT_PREFIX=$AMENT_CURRENT_PREFIX
+
+# trace output
+if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
+ echo "# . \"$_this_path/local_setup.sh\""
+fi
+. "$_this_path/local_setup.sh"
+unset _this_path
+
+# unset AMENT_ENVIRONMENT_HOOKS
+# if not appending to them for return
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+# restore AMENT_CURRENT_PREFIX before evaluating the environment hooks
+AMENT_CURRENT_PREFIX=$_package_local_setup_AMENT_CURRENT_PREFIX
+# list all environment hooks of this package
+
+# source all shell-specific environment hooks of this package
+# if not returning them
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ _package_local_setup_IFS=$IFS
+ IFS=":"
+ for _hook in $AMENT_ENVIRONMENT_HOOKS; do
+ # restore AMENT_CURRENT_PREFIX for each environment hook
+ AMENT_CURRENT_PREFIX=$_package_local_setup_AMENT_CURRENT_PREFIX
+ # restore IFS before sourcing other files
+ IFS=$_package_local_setup_IFS
+ . "$_hook"
+ done
+ unset _hook
+ IFS=$_package_local_setup_IFS
+ unset _package_local_setup_IFS
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+unset _package_local_setup_AMENT_CURRENT_PREFIX
+unset AMENT_CURRENT_PREFIX
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.dsv b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.dsv
new file mode 100644
index 0000000..caf412a
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.dsv
@@ -0,0 +1,2 @@
+source;share/ros_viz_adapter/environment/ament_prefix_path.sh
+source;share/ros_viz_adapter/environment/path.sh
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.sh b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.sh
new file mode 100644
index 0000000..ab4af87
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.sh
@@ -0,0 +1,184 @@
+# generated from ament_package/template/package_level/local_setup.sh.in
+
+# since this file is sourced use either the provided AMENT_CURRENT_PREFIX
+# or fall back to the destination set at configure time
+: ${AMENT_CURRENT_PREFIX:="/workspace/install/ros_viz_adapter"}
+if [ ! -d "$AMENT_CURRENT_PREFIX" ]; then
+ if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+ echo "The compile time prefix path '$AMENT_CURRENT_PREFIX' doesn't " \
+ "exist. Consider sourcing a different extension than '.sh'." 1>&2
+ else
+ AMENT_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+ fi
+fi
+
+# function to append values to environment variables
+# using colons as separators and avoiding leading separators
+ament_append_value() {
+ # arguments
+ _listname="$1"
+ _value="$2"
+ #echo "listname $_listname"
+ #eval echo "list value \$$_listname"
+ #echo "value $_value"
+
+ # avoid leading separator
+ eval _values=\"\$$_listname\"
+ if [ -z "$_values" ]; then
+ eval export $_listname=\"$_value\"
+ #eval echo "set list \$$_listname"
+ else
+ # field separator must not be a colon
+ _ament_append_value_IFS=$IFS
+ unset IFS
+ eval export $_listname=\"\$$_listname:$_value\"
+ #eval echo "append list \$$_listname"
+ IFS=$_ament_append_value_IFS
+ unset _ament_append_value_IFS
+ fi
+ unset _values
+
+ unset _value
+ unset _listname
+}
+
+# function to append non-duplicate values to environment variables
+# using colons as separators and avoiding leading separators
+ament_append_unique_value() {
+ # arguments
+ _listname=$1
+ _value=$2
+ #echo "listname $_listname"
+ #eval echo "list value \$$_listname"
+ #echo "value $_value"
+
+ # check if the list contains the value
+ eval _values=\$$_listname
+ _duplicate=
+ _ament_append_unique_value_IFS=$IFS
+ IFS=":"
+ if [ "$AMENT_SHELL" = "zsh" ]; then
+ ament_zsh_to_array _values
+ fi
+ for _item in $_values; do
+ # ignore empty strings
+ if [ -z "$_item" ]; then
+ continue
+ fi
+ if [ $_item = $_value ]; then
+ _duplicate=1
+ fi
+ done
+ unset _item
+
+ # append only non-duplicates
+ if [ -z "$_duplicate" ]; then
+ # avoid leading separator
+ if [ -z "$_values" ]; then
+ eval $_listname=\"$_value\"
+ #eval echo "set list \$$_listname"
+ else
+ # field separator must not be a colon
+ unset IFS
+ eval $_listname=\"\$$_listname:$_value\"
+ #eval echo "append list \$$_listname"
+ fi
+ fi
+ IFS=$_ament_append_unique_value_IFS
+ unset _ament_append_unique_value_IFS
+ unset _duplicate
+ unset _values
+
+ unset _value
+ unset _listname
+}
+
+# function to prepend non-duplicate values to environment variables
+# using colons as separators and avoiding trailing separators
+ament_prepend_unique_value() {
+ # arguments
+ _listname="$1"
+ _value="$2"
+ #echo "listname $_listname"
+ #eval echo "list value \$$_listname"
+ #echo "value $_value"
+
+ # check if the list contains the value
+ eval _values=\"\$$_listname\"
+ _duplicate=
+ _ament_prepend_unique_value_IFS=$IFS
+ IFS=":"
+ if [ "$AMENT_SHELL" = "zsh" ]; then
+ ament_zsh_to_array _values
+ fi
+ for _item in $_values; do
+ # ignore empty strings
+ if [ -z "$_item" ]; then
+ continue
+ fi
+ if [ "$_item" = "$_value" ]; then
+ _duplicate=1
+ fi
+ done
+ unset _item
+
+ # prepend only non-duplicates
+ if [ -z "$_duplicate" ]; then
+ # avoid trailing separator
+ if [ -z "$_values" ]; then
+ eval export $_listname=\"$_value\"
+ #eval echo "set list \$$_listname"
+ else
+ # field separator must not be a colon
+ unset IFS
+ eval export $_listname=\"$_value:\$$_listname\"
+ #eval echo "prepend list \$$_listname"
+ fi
+ fi
+ IFS=$_ament_prepend_unique_value_IFS
+ unset _ament_prepend_unique_value_IFS
+ unset _duplicate
+ unset _values
+
+ unset _value
+ unset _listname
+}
+
+# unset AMENT_ENVIRONMENT_HOOKS
+# if not appending to them for return
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+# list all environment hooks of this package
+ament_append_value AMENT_ENVIRONMENT_HOOKS "$AMENT_CURRENT_PREFIX/share/ros_viz_adapter/environment/ament_prefix_path.sh"
+ament_append_value AMENT_ENVIRONMENT_HOOKS "$AMENT_CURRENT_PREFIX/share/ros_viz_adapter/environment/path.sh"
+
+# source all shell-specific environment hooks of this package
+# if not returning them
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ _package_local_setup_IFS=$IFS
+ IFS=":"
+ if [ "$AMENT_SHELL" = "zsh" ]; then
+ ament_zsh_to_array AMENT_ENVIRONMENT_HOOKS
+ fi
+ for _hook in $AMENT_ENVIRONMENT_HOOKS; do
+ if [ -f "$_hook" ]; then
+ # restore IFS before sourcing other files
+ IFS=$_package_local_setup_IFS
+ # trace output
+ if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
+ echo "# . \"$_hook\""
+ fi
+ . "$_hook"
+ fi
+ done
+ unset _hook
+ IFS=$_package_local_setup_IFS
+ unset _package_local_setup_IFS
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+# reset AMENT_CURRENT_PREFIX after each package
+# allowing to source multiple package-level setup files
+unset AMENT_CURRENT_PREFIX
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.zsh b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.zsh
new file mode 100644
index 0000000..fe161be
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/local_setup.zsh
@@ -0,0 +1,59 @@
+# generated from ament_package/template/package_level/local_setup.zsh.in
+
+AMENT_SHELL=zsh
+
+# source local_setup.sh from same directory as this file
+_this_path=$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)
+# provide AMENT_CURRENT_PREFIX to shell script
+AMENT_CURRENT_PREFIX=$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)
+# store AMENT_CURRENT_PREFIX to restore it before each environment hook
+_package_local_setup_AMENT_CURRENT_PREFIX=$AMENT_CURRENT_PREFIX
+
+# function to convert array-like strings into arrays
+# to wordaround SH_WORD_SPLIT not being set
+ament_zsh_to_array() {
+ local _listname=$1
+ local _dollar="$"
+ local _split="{="
+ local _to_array="(\"$_dollar$_split$_listname}\")"
+ eval $_listname=$_to_array
+}
+
+# trace output
+if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
+ echo "# . \"$_this_path/local_setup.sh\""
+fi
+# the package-level local_setup file unsets AMENT_CURRENT_PREFIX
+. "$_this_path/local_setup.sh"
+unset _this_path
+
+# unset AMENT_ENVIRONMENT_HOOKS
+# if not appending to them for return
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+# restore AMENT_CURRENT_PREFIX before evaluating the environment hooks
+AMENT_CURRENT_PREFIX=$_package_local_setup_AMENT_CURRENT_PREFIX
+# list all environment hooks of this package
+
+# source all shell-specific environment hooks of this package
+# if not returning them
+if [ -z "$AMENT_RETURN_ENVIRONMENT_HOOKS" ]; then
+ _package_local_setup_IFS=$IFS
+ IFS=":"
+ for _hook in $AMENT_ENVIRONMENT_HOOKS; do
+ # restore AMENT_CURRENT_PREFIX for each environment hook
+ AMENT_CURRENT_PREFIX=$_package_local_setup_AMENT_CURRENT_PREFIX
+ # restore IFS before sourcing other files
+ IFS=$_package_local_setup_IFS
+ . "$_hook"
+ done
+ unset _hook
+ IFS=$_package_local_setup_IFS
+ unset _package_local_setup_IFS
+ unset AMENT_ENVIRONMENT_HOOKS
+fi
+
+unset _package_local_setup_AMENT_CURRENT_PREFIX
+unset AMENT_CURRENT_PREFIX
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.bash b/install/ros_viz_adapter/share/ros_viz_adapter/package.bash
new file mode 100644
index 0000000..02c8491
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.bash
@@ -0,0 +1,39 @@
+# generated from colcon_bash/shell/template/package.bash.em
+
+# This script extends the environment for this package.
+
+# a bash script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+ # the prefix is two levels up from the package specific share directory
+ _colcon_package_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." > /dev/null && pwd)"
+else
+ _colcon_package_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_bash_source_script() {
+ if [ -f "$1" ]; then
+ if [ -n "$COLCON_TRACE" ]; then
+ echo "# . \"$1\""
+ fi
+ . "$@"
+ else
+ echo "not found: \"$1\"" 1>&2
+ fi
+}
+
+# source sh script of this package
+_colcon_package_bash_source_script "$_colcon_package_bash_COLCON_CURRENT_PREFIX/share/ros_viz_adapter/package.sh"
+
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced scripts
+COLCON_CURRENT_PREFIX="$_colcon_package_bash_COLCON_CURRENT_PREFIX"
+
+# source bash hooks
+_colcon_package_bash_source_script "$COLCON_CURRENT_PREFIX/share/ros_viz_adapter/local_setup.bash"
+
+unset COLCON_CURRENT_PREFIX
+
+unset _colcon_package_bash_source_script
+unset _colcon_package_bash_COLCON_CURRENT_PREFIX
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.dsv b/install/ros_viz_adapter/share/ros_viz_adapter/package.dsv
new file mode 100644
index 0000000..64630a0
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.dsv
@@ -0,0 +1,8 @@
+source;share/ros_viz_adapter/hook/cmake_prefix_path.ps1
+source;share/ros_viz_adapter/hook/cmake_prefix_path.dsv
+source;share/ros_viz_adapter/hook/cmake_prefix_path.sh
+source;share/ros_viz_adapter/local_setup.bash
+source;share/ros_viz_adapter/local_setup.dsv
+source;share/ros_viz_adapter/local_setup.ps1
+source;share/ros_viz_adapter/local_setup.sh
+source;share/ros_viz_adapter/local_setup.zsh
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.ps1 b/install/ros_viz_adapter/share/ros_viz_adapter/package.ps1
new file mode 100644
index 0000000..4b9923c
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.ps1
@@ -0,0 +1,116 @@
+# generated from colcon_powershell/shell/template/package.ps1.em
+
+# function to append a value to a variable
+# which uses colons as separators
+# duplicates as well as leading separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_append_unique_value {
+ param (
+ $_listname,
+ $_value
+ )
+
+ # get values from variable
+ if (Test-Path Env:$_listname) {
+ $_values=(Get-Item env:$_listname).Value
+ } else {
+ $_values=""
+ }
+ $_duplicate=""
+ # start with no values
+ $_all_values=""
+ # iterate over existing values in the variable
+ if ($_values) {
+ $_values.Split(":") | ForEach {
+ # not an empty string
+ if ($_) {
+ # not a duplicate of _value
+ if ($_ -eq $_value) {
+ $_duplicate="1"
+ }
+ if ($_all_values) {
+ $_all_values="${_all_values}:$_"
+ } else {
+ $_all_values="$_"
+ }
+ }
+ }
+ }
+ # append only non-duplicates
+ if (!$_duplicate) {
+ # avoid leading separator
+ if ($_all_values) {
+ $_all_values="${_all_values}:${_value}"
+ } else {
+ $_all_values="${_value}"
+ }
+ }
+
+ # export the updated variable
+ Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_prepend_unique_value {
+ param (
+ $_listname,
+ $_value
+ )
+
+ # get values from variable
+ if (Test-Path Env:$_listname) {
+ $_values=(Get-Item env:$_listname).Value
+ } else {
+ $_values=""
+ }
+ # start with the new value
+ $_all_values="$_value"
+ # iterate over existing values in the variable
+ if ($_values) {
+ $_values.Split(":") | ForEach {
+ # not an empty string
+ if ($_) {
+ # not a duplicate of _value
+ if ($_ -ne $_value) {
+ # keep non-duplicate values
+ $_all_values="${_all_values}:$_"
+ }
+ }
+ }
+ }
+ # export the updated variable
+ Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+function colcon_package_source_powershell_script {
+ param (
+ $_colcon_package_source_powershell_script
+ )
+ # source script with conditional trace output
+ if (Test-Path $_colcon_package_source_powershell_script) {
+ if ($env:COLCON_TRACE) {
+ echo ". '$_colcon_package_source_powershell_script'"
+ }
+ . "$_colcon_package_source_powershell_script"
+ } else {
+ Write-Error "not found: '$_colcon_package_source_powershell_script'"
+ }
+}
+
+
+# a powershell script is able to determine its own path
+# the prefix is two levels up from the package specific share directory
+$env:COLCON_CURRENT_PREFIX=(Get-Item $PSCommandPath).Directory.Parent.Parent.FullName
+
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX/share/ros_viz_adapter/hook/cmake_prefix_path.ps1"
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX/share/ros_viz_adapter/local_setup.ps1"
+
+Remove-Item Env:\COLCON_CURRENT_PREFIX
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.sh b/install/ros_viz_adapter/share/ros_viz_adapter/package.sh
new file mode 100644
index 0000000..786b881
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.sh
@@ -0,0 +1,87 @@
+# generated from colcon_core/shell/template/package.sh.em
+
+# This script extends the environment for this package.
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prepend_unique_value() {
+ # arguments
+ _listname="$1"
+ _value="$2"
+
+ # get values from variable
+ eval _values=\"\$$_listname\"
+ # backup the field separator
+ _colcon_prepend_unique_value_IFS=$IFS
+ IFS=":"
+ # start with the new value
+ _all_values="$_value"
+ # workaround SH_WORD_SPLIT not being set in zsh
+ if [ "$(command -v colcon_zsh_convert_to_array)" ]; then
+ colcon_zsh_convert_to_array _values
+ fi
+ # iterate over existing values in the variable
+ for _item in $_values; do
+ # ignore empty strings
+ if [ -z "$_item" ]; then
+ continue
+ fi
+ # ignore duplicates of _value
+ if [ "$_item" = "$_value" ]; then
+ continue
+ fi
+ # keep non-duplicate values
+ _all_values="$_all_values:$_item"
+ done
+ unset _item
+ # restore the field separator
+ IFS=$_colcon_prepend_unique_value_IFS
+ unset _colcon_prepend_unique_value_IFS
+ # export the updated variable
+ eval export $_listname=\"$_all_values\"
+ unset _all_values
+ unset _values
+
+ unset _value
+ unset _listname
+}
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_package_sh_COLCON_CURRENT_PREFIX="/workspace/install/ros_viz_adapter"
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+ if [ ! -d "$_colcon_package_sh_COLCON_CURRENT_PREFIX" ]; then
+ echo "The build time path \"$_colcon_package_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2
+ unset _colcon_package_sh_COLCON_CURRENT_PREFIX
+ return 1
+ fi
+ COLCON_CURRENT_PREFIX="$_colcon_package_sh_COLCON_CURRENT_PREFIX"
+fi
+unset _colcon_package_sh_COLCON_CURRENT_PREFIX
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_sh_source_script() {
+ if [ -f "$1" ]; then
+ if [ -n "$COLCON_TRACE" ]; then
+ echo "# . \"$1\""
+ fi
+ . "$@"
+ else
+ echo "not found: \"$1\"" 1>&2
+ fi
+}
+
+# source sh hooks
+_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/ros_viz_adapter/hook/cmake_prefix_path.sh"
+_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/ros_viz_adapter/local_setup.sh"
+
+unset _colcon_package_sh_source_script
+unset COLCON_CURRENT_PREFIX
+
+# do not unset _colcon_prepend_unique_value since it might be used by non-primary shell hooks
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.xml b/install/ros_viz_adapter/share/ros_viz_adapter/package.xml
new file mode 100644
index 0000000..d489790
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.xml
@@ -0,0 +1,16 @@
+
+
+ ros_viz_adapter
+ 0.2.0
+ Rate-limited ROS 2 visualization publishers for images and point clouds.
+ Platform Team
+ Apache-2.0
+ ament_cmake
+ rclcpp
+ sensor_msgs
+ image_transport
+ pluginlib
+ compressed_image_transport
+ compressed_depth_image_transport
+ ament_cmake
+
diff --git a/install/ros_viz_adapter/share/ros_viz_adapter/package.zsh b/install/ros_viz_adapter/share/ros_viz_adapter/package.zsh
new file mode 100644
index 0000000..1a523ad
--- /dev/null
+++ b/install/ros_viz_adapter/share/ros_viz_adapter/package.zsh
@@ -0,0 +1,50 @@
+# generated from colcon_zsh/shell/template/package.zsh.em
+
+# This script extends the environment for this package.
+
+# a zsh script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+ # the prefix is two levels up from the package specific share directory
+ _colcon_package_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)"
+else
+ _colcon_package_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_zsh_source_script() {
+ if [ -f "$1" ]; then
+ if [ -n "$COLCON_TRACE" ]; then
+ echo "# . \"$1\""
+ fi
+ . "$@"
+ else
+ echo "not found: \"$1\"" 1>&2
+ fi
+}
+
+# function to convert array-like strings into arrays
+# to workaround SH_WORD_SPLIT not being set
+colcon_zsh_convert_to_array() {
+ local _listname=$1
+ local _dollar="$"
+ local _split="{="
+ local _to_array="(\"$_dollar$_split$_listname}\")"
+ eval $_listname=$_to_array
+}
+
+# source sh script of this package
+_colcon_package_zsh_source_script "$_colcon_package_zsh_COLCON_CURRENT_PREFIX/share/ros_viz_adapter/package.sh"
+unset convert_zsh_to_array
+
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced scripts
+COLCON_CURRENT_PREFIX="$_colcon_package_zsh_COLCON_CURRENT_PREFIX"
+
+# source zsh hooks
+_colcon_package_zsh_source_script "$COLCON_CURRENT_PREFIX/share/ros_viz_adapter/local_setup.zsh"
+
+unset COLCON_CURRENT_PREFIX
+
+unset _colcon_package_zsh_source_script
+unset _colcon_package_zsh_COLCON_CURRENT_PREFIX